
/*****
*
* Copyright (C) 2001-2017 CS-SI. All Rights Reserved.
* Author: Yoann Vandoorselaere <yoann.v@prelude-ids.com>
* Author: Nicolas Delon <nicolas.delon@prelude-ids.com>
*
* This file is part of the Prelude library.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*****/

/* Auto-generated by the GenerateIDMEFTreeWrapC package */

#include "config.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>

#include "prelude-inttypes.h"
#include "prelude-list.h"
#include "prelude-msg.h"
#include "prelude-string.h"

#define PRELUDE_ERROR_SOURCE_DEFAULT PRELUDE_ERROR_SOURCE_IDMEF_TREE_WRAP
#include "prelude-error.h"

#include "idmef-time.h"
#include "idmef-data.h"
#include "idmef-class.h"
#include "idmef-value.h"
#include "idmef-object-prv.h"

#include "idmef-tree-wrap.h"
#include "libmissing.h"
#include "common.h"

#ifdef WIN32
# undef interface
#endif


#define LISTED_OBJECT(name, type) prelude_list_t name
#define KEYLISTED_OBJECT(name, type) prelude_list_t name

#define IS_KEY_LISTED(keyfield) IDMEF_LINKED_OBJECT; prelude_string_t *keyfield

#define UNION(type, var) type var; union

#define UNION_MEMBER(value, type, name) type name

#define ENUM(...) typedef enum

#define PRE_DECLARE(type, class)

#define TYPE_ID(type, id) type

#define PRIMITIVE_TYPE(type)
#define PRIMITIVE_TYPE_STRUCT(type)

#define HIDE(type, name) type name

#define REFCOUNT int refcount
#define REQUIRED(type, name) type name
#define IGNORED(type, name) type name

#define DYNAMIC_IDENT(x) uint64_t x

#define OPTIONAL_INT(type, name) type name; unsigned int name ## _is_set:1

#define IDENT(name) uint64_t name


#define idmef_data_copy idmef_data_copy_dup

#ifndef ABS
# define ABS(x) (((x) < 0) ? -(x) : (x))
#endif


/*
 * If we subtract the integer representations of two floats then that
 * will tell us how close they are. If the difference is zero, they are
 * identical. If the difference is one, they are adjacent floats.
 * In general, if the difference is n then there are n-1 floats between
 * them.
 *
 * http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
 */
static int float_compare(float a, float b)
{
        union {
                float fval;
                int32_t ival;
        } au, bu;

        au.fval = a;
        bu.fval = b;

        /* Make aInt lexicographically ordered as a twos-complement int */
        if ( au.ival < 0 )
                au.ival = 0x80000000 - au.ival;

        /* Make bInt lexicographically ordered as a twos-complement int */
        if ( bu.ival < 0 )
                bu.ival = 0x80000000 - bu.ival;

        return (ABS(au.ival - bu.ival) <= 0) ? 0 : -1;
}



static int prelude_string_copy(const prelude_string_t *src, prelude_string_t *dst)
{
        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));
        prelude_return_val_if_fail(dst, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! prelude_string_is_empty(src) )
               return prelude_string_copy_dup(src, dst);

        return 0;
}



static int get_value_from_string(idmef_value_t **value, prelude_string_t *str, prelude_bool_t is_ptr)
{
        int ret;

        if ( ! str ) {
                *value = NULL;
                return 0;
        }

        if ( ! is_ptr ) {
                ret = prelude_string_clone(str, &str);
                if ( ret < 0 )
                        return ret;
        }

        ret = idmef_value_new_string(value, str);
        if ( ret < 0 ) {
                prelude_string_destroy(str);
                return ret;
        }

        if ( is_ptr )
                prelude_string_ref(str);

        return 0;
}



static int get_value_from_data(idmef_value_t **value, idmef_data_t *data, prelude_bool_t is_ptr)
{
        int ret;

        if ( ! data ) {
                *value = NULL;
                return 0;
        }

        if ( ! is_ptr ) {
                ret = idmef_data_clone(data, &data);
                if ( ret < 0 )
                        return ret;
        }

        ret = idmef_value_new_data(value, data);
        if ( ret < 0 ) {
                idmef_data_destroy(data);
                return ret;
        }

        if ( is_ptr )
                idmef_data_ref(data);

        return 0;
}


static int get_value_from_time(idmef_value_t **value, idmef_time_t *time, prelude_bool_t is_ptr)
{
        int ret;

        if ( ! time ) {
                *value = NULL;
                return 0;
        }

        if ( ! is_ptr ) {
                ret = idmef_time_clone(time, &time);
                if ( ret < 0 )
                        return ret;
        }

        ret = idmef_value_new_time(value, time);
        if ( ret < 0 ) {
                idmef_time_destroy(time);
                return ret;
        }

        if ( is_ptr )
                idmef_time_ref(time);

        return 0;
}


static void list_insert(prelude_list_t *head, prelude_list_t *item, int pos)
{
        int i = 0;
        prelude_list_t *tmp;

        if ( pos == IDMEF_LIST_APPEND )
                prelude_list_add_tail(head, item);

        else if ( pos == IDMEF_LIST_PREPEND )
                prelude_list_add(head, item);

        else if ( pos >= 0 ) {
                prelude_list_for_each(head, tmp) {
                        if ( i == pos )
                                break;
                        i++;
                }

                prelude_list_add_tail(tmp, item);
        }

        else if ( pos < 0 ) {
                pos = -pos;
                pos--;

                prelude_list_for_each_reversed(head, tmp) {
                        if ( i == pos )
                                break;
                        i++;
                }

                prelude_list_add(tmp, item);
        }
}


/**
 * idmef_additional_data_type_to_numeric:
 * @name: pointer to an IDMEF string representation of a #idmef_additional_data_type_t value.
 *
 * Returns: the numeric equivalent of @name, or -1 if @name is not valid.
 */
idmef_additional_data_type_t idmef_additional_data_type_to_numeric(const char *name)
{
        size_t i;
        const struct {
              idmef_additional_data_type_t val;
              const char *name;
        } tbl[] = {
            { IDMEF_ADDITIONAL_DATA_TYPE_STRING, "string" },
            { IDMEF_ADDITIONAL_DATA_TYPE_BYTE, "byte" },
            { IDMEF_ADDITIONAL_DATA_TYPE_CHARACTER, "character" },
            { IDMEF_ADDITIONAL_DATA_TYPE_DATE_TIME, "date-time" },
            { IDMEF_ADDITIONAL_DATA_TYPE_INTEGER, "integer" },
            { IDMEF_ADDITIONAL_DATA_TYPE_NTPSTAMP, "ntpstamp" },
            { IDMEF_ADDITIONAL_DATA_TYPE_PORTLIST, "portlist" },
            { IDMEF_ADDITIONAL_DATA_TYPE_REAL, "real" },
            { IDMEF_ADDITIONAL_DATA_TYPE_BOOLEAN, "boolean" },
            { IDMEF_ADDITIONAL_DATA_TYPE_BYTE_STRING, "byte-string" },
            { IDMEF_ADDITIONAL_DATA_TYPE_XML, "xml" },
        };

        prelude_return_val_if_fail(name, prelude_error(PRELUDE_ERROR_ASSERTION));

        for ( i = 0; i < sizeof(tbl) / sizeof(*tbl); i++ ) {
                if ( strcasecmp(name, tbl[i].name) == 0 )
                        return tbl[i].val;
        }

        return prelude_error_verbose(PRELUDE_ERROR_IDMEF_UNKNOWN_ENUM_STRING, "Unknown enumeration value '%s' for additional_data_type", name);
}

/**
 * idmef_additional_data_type_to_string:
 * @val: an enumeration value for #idmef_additional_data_type_t.
 *
 * Return the IDMEF string equivalent of @val provided #idmef_additional_data_type_t value.
 *
 * Returns: a pointer to the string describing @val, or NULL if @val is invalid.
 */
const char *idmef_additional_data_type_to_string(idmef_additional_data_type_t val)
{
        const struct {
              idmef_additional_data_type_t val;
              const char *name;
        } tbl[] = {
                { IDMEF_ADDITIONAL_DATA_TYPE_STRING, "string" },
                { IDMEF_ADDITIONAL_DATA_TYPE_BYTE, "byte" },
                { IDMEF_ADDITIONAL_DATA_TYPE_CHARACTER, "character" },
                { IDMEF_ADDITIONAL_DATA_TYPE_DATE_TIME, "date-time" },
                { IDMEF_ADDITIONAL_DATA_TYPE_INTEGER, "integer" },
                { IDMEF_ADDITIONAL_DATA_TYPE_NTPSTAMP, "ntpstamp" },
                { IDMEF_ADDITIONAL_DATA_TYPE_PORTLIST, "portlist" },
                { IDMEF_ADDITIONAL_DATA_TYPE_REAL, "real" },
                { IDMEF_ADDITIONAL_DATA_TYPE_BOOLEAN, "boolean" },
                { IDMEF_ADDITIONAL_DATA_TYPE_BYTE_STRING, "byte-string" },
                { IDMEF_ADDITIONAL_DATA_TYPE_XML, "xml" },
        };

        if ( val < 0 || (size_t) val >= (sizeof(tbl) / sizeof(*tbl)) )
                return NULL;

        return tbl[val].name;
}


struct idmef_additional_data {
 
         IS_KEY_LISTED(meaning);
         REFCOUNT;
         IGNORED(prelude_bool_t, _type_is_set);
         idmef_additional_data_type_t type;
         REQUIRED(idmef_data_t, *data);
 
};


/**
 * idmef_reference_origin_to_numeric:
 * @name: pointer to an IDMEF string representation of a #idmef_reference_origin_t value.
 *
 * Returns: the numeric equivalent of @name, or -1 if @name is not valid.
 */
idmef_reference_origin_t idmef_reference_origin_to_numeric(const char *name)
{
        size_t i;
        const struct {
              idmef_reference_origin_t val;
              const char *name;
        } tbl[] = {
            { IDMEF_REFERENCE_ORIGIN_UNKNOWN, "unknown" },
            { IDMEF_REFERENCE_ORIGIN_VENDOR_SPECIFIC, "vendor-specific" },
            { IDMEF_REFERENCE_ORIGIN_USER_SPECIFIC, "user-specific" },
            { IDMEF_REFERENCE_ORIGIN_BUGTRAQID, "bugtraqid" },
            { IDMEF_REFERENCE_ORIGIN_CVE, "cve" },
            { IDMEF_REFERENCE_ORIGIN_OSVDB, "osvdb" },
        };

        prelude_return_val_if_fail(name, prelude_error(PRELUDE_ERROR_ASSERTION));

        for ( i = 0; i < sizeof(tbl) / sizeof(*tbl); i++ ) {
                if ( strcasecmp(name, tbl[i].name) == 0 )
                        return tbl[i].val;
        }

        return prelude_error_verbose(PRELUDE_ERROR_IDMEF_UNKNOWN_ENUM_STRING, "Unknown enumeration value '%s' for reference_origin", name);
}

/**
 * idmef_reference_origin_to_string:
 * @val: an enumeration value for #idmef_reference_origin_t.
 *
 * Return the IDMEF string equivalent of @val provided #idmef_reference_origin_t value.
 *
 * Returns: a pointer to the string describing @val, or NULL if @val is invalid.
 */
const char *idmef_reference_origin_to_string(idmef_reference_origin_t val)
{
        const struct {
              idmef_reference_origin_t val;
              const char *name;
        } tbl[] = {
                { IDMEF_REFERENCE_ORIGIN_UNKNOWN, "unknown" },
                { IDMEF_REFERENCE_ORIGIN_VENDOR_SPECIFIC, "vendor-specific" },
                { IDMEF_REFERENCE_ORIGIN_USER_SPECIFIC, "user-specific" },
                { IDMEF_REFERENCE_ORIGIN_BUGTRAQID, "bugtraqid" },
                { IDMEF_REFERENCE_ORIGIN_CVE, "cve" },
                { IDMEF_REFERENCE_ORIGIN_OSVDB, "osvdb" },
        };

        if ( val < 0 || (size_t) val >= (sizeof(tbl) / sizeof(*tbl)) )
                return NULL;

        return tbl[val].name;
}


struct idmef_reference {
 
         IDMEF_LINKED_OBJECT;
         REFCOUNT;
         idmef_reference_origin_t origin;
 
         REQUIRED(prelude_string_t, *name);
         REQUIRED(prelude_string_t, *url);
         prelude_string_t *meaning;
 
};



struct idmef_classification {
 
         IDMEF_OBJECT;
         REFCOUNT;
         prelude_string_t *ident;
         REQUIRED(prelude_string_t, *text);
         LISTED_OBJECT(reference_list, idmef_reference_t);
 
 
};


/**
 * idmef_user_id_type_to_numeric:
 * @name: pointer to an IDMEF string representation of a #idmef_user_id_type_t value.
 *
 * Returns: the numeric equivalent of @name, or -1 if @name is not valid.
 */
idmef_user_id_type_t idmef_user_id_type_to_numeric(const char *name)
{
        size_t i;
        const struct {
              idmef_user_id_type_t val;
              const char *name;
        } tbl[] = {
            { IDMEF_USER_ID_TYPE_ORIGINAL_USER, "original-user" },
            { IDMEF_USER_ID_TYPE_CURRENT_USER, "current-user" },
            { IDMEF_USER_ID_TYPE_TARGET_USER, "target-user" },
            { IDMEF_USER_ID_TYPE_USER_PRIVS, "user-privs" },
            { IDMEF_USER_ID_TYPE_CURRENT_GROUP, "current-group" },
            { IDMEF_USER_ID_TYPE_GROUP_PRIVS, "group-privs" },
            { IDMEF_USER_ID_TYPE_OTHER_PRIVS, "other-privs" },
        };

        prelude_return_val_if_fail(name, prelude_error(PRELUDE_ERROR_ASSERTION));

        for ( i = 0; i < sizeof(tbl) / sizeof(*tbl); i++ ) {
                if ( strcasecmp(name, tbl[i].name) == 0 )
                        return tbl[i].val;
        }

        return prelude_error_verbose(PRELUDE_ERROR_IDMEF_UNKNOWN_ENUM_STRING, "Unknown enumeration value '%s' for user_id_type", name);
}

/**
 * idmef_user_id_type_to_string:
 * @val: an enumeration value for #idmef_user_id_type_t.
 *
 * Return the IDMEF string equivalent of @val provided #idmef_user_id_type_t value.
 *
 * Returns: a pointer to the string describing @val, or NULL if @val is invalid.
 */
const char *idmef_user_id_type_to_string(idmef_user_id_type_t val)
{
        const struct {
              idmef_user_id_type_t val;
              const char *name;
        } tbl[] = {
                { IDMEF_USER_ID_TYPE_ORIGINAL_USER, "original-user" },
                { IDMEF_USER_ID_TYPE_CURRENT_USER, "current-user" },
                { IDMEF_USER_ID_TYPE_TARGET_USER, "target-user" },
                { IDMEF_USER_ID_TYPE_USER_PRIVS, "user-privs" },
                { IDMEF_USER_ID_TYPE_CURRENT_GROUP, "current-group" },
                { IDMEF_USER_ID_TYPE_GROUP_PRIVS, "group-privs" },
                { IDMEF_USER_ID_TYPE_OTHER_PRIVS, "other-privs" },
        };

        if ( val < 0 || (size_t) val >= (sizeof(tbl) / sizeof(*tbl)) )
                return NULL;

        return tbl[val].name;
}


struct idmef_user_id {
 
         IDMEF_LINKED_OBJECT;
         REFCOUNT;
         prelude_string_t *ident;
         idmef_user_id_type_t type;
         prelude_string_t *tty;
         prelude_string_t *name;
         OPTIONAL_INT(uint32_t, number);
 
};


/**
 * idmef_user_category_to_numeric:
 * @name: pointer to an IDMEF string representation of a #idmef_user_category_t value.
 *
 * Returns: the numeric equivalent of @name, or -1 if @name is not valid.
 */
idmef_user_category_t idmef_user_category_to_numeric(const char *name)
{
        size_t i;
        const struct {
              idmef_user_category_t val;
              const char *name;
        } tbl[] = {
            { IDMEF_USER_CATEGORY_UNKNOWN, "unknown" },
            { IDMEF_USER_CATEGORY_APPLICATION, "application" },
            { IDMEF_USER_CATEGORY_OS_DEVICE, "os-device" },
        };

        prelude_return_val_if_fail(name, prelude_error(PRELUDE_ERROR_ASSERTION));

        for ( i = 0; i < sizeof(tbl) / sizeof(*tbl); i++ ) {
                if ( strcasecmp(name, tbl[i].name) == 0 )
                        return tbl[i].val;
        }

        return prelude_error_verbose(PRELUDE_ERROR_IDMEF_UNKNOWN_ENUM_STRING, "Unknown enumeration value '%s' for user_category", name);
}

/**
 * idmef_user_category_to_string:
 * @val: an enumeration value for #idmef_user_category_t.
 *
 * Return the IDMEF string equivalent of @val provided #idmef_user_category_t value.
 *
 * Returns: a pointer to the string describing @val, or NULL if @val is invalid.
 */
const char *idmef_user_category_to_string(idmef_user_category_t val)
{
        const struct {
              idmef_user_category_t val;
              const char *name;
        } tbl[] = {
                { IDMEF_USER_CATEGORY_UNKNOWN, "unknown" },
                { IDMEF_USER_CATEGORY_APPLICATION, "application" },
                { IDMEF_USER_CATEGORY_OS_DEVICE, "os-device" },
        };

        if ( val < 0 || (size_t) val >= (sizeof(tbl) / sizeof(*tbl)) )
                return NULL;

        return tbl[val].name;
}


struct idmef_user {
 
         IDMEF_OBJECT;
         REFCOUNT;
         prelude_string_t *ident;
         idmef_user_category_t category;
         LISTED_OBJECT(user_id_list, idmef_user_id_t);
 
};


/**
 * idmef_address_category_to_numeric:
 * @name: pointer to an IDMEF string representation of a #idmef_address_category_t value.
 *
 * Returns: the numeric equivalent of @name, or -1 if @name is not valid.
 */
idmef_address_category_t idmef_address_category_to_numeric(const char *name)
{
        size_t i;
        const struct {
              idmef_address_category_t val;
              const char *name;
        } tbl[] = {
            { IDMEF_ADDRESS_CATEGORY_UNKNOWN, "unknown" },
            { IDMEF_ADDRESS_CATEGORY_ATM, "atm" },
            { IDMEF_ADDRESS_CATEGORY_E_MAIL, "e-mail" },
            { IDMEF_ADDRESS_CATEGORY_LOTUS_NOTES, "lotus-notes" },
            { IDMEF_ADDRESS_CATEGORY_MAC, "mac" },
            { IDMEF_ADDRESS_CATEGORY_SNA, "sna" },
            { IDMEF_ADDRESS_CATEGORY_VM, "vm" },
            { IDMEF_ADDRESS_CATEGORY_IPV4_ADDR, "ipv4-addr" },
            { IDMEF_ADDRESS_CATEGORY_IPV4_ADDR_HEX, "ipv4-addr-hex" },
            { IDMEF_ADDRESS_CATEGORY_IPV4_NET, "ipv4-net" },
            { IDMEF_ADDRESS_CATEGORY_IPV4_NET_MASK, "ipv4-net-mask" },
            { IDMEF_ADDRESS_CATEGORY_IPV6_ADDR, "ipv6-addr" },
            { IDMEF_ADDRESS_CATEGORY_IPV6_ADDR_HEX, "ipv6-addr-hex" },
            { IDMEF_ADDRESS_CATEGORY_IPV6_NET, "ipv6-net" },
            { IDMEF_ADDRESS_CATEGORY_IPV6_NET_MASK, "ipv6-net-mask" },
        };

        prelude_return_val_if_fail(name, prelude_error(PRELUDE_ERROR_ASSERTION));

        for ( i = 0; i < sizeof(tbl) / sizeof(*tbl); i++ ) {
                if ( strcasecmp(name, tbl[i].name) == 0 )
                        return tbl[i].val;
        }

        return prelude_error_verbose(PRELUDE_ERROR_IDMEF_UNKNOWN_ENUM_STRING, "Unknown enumeration value '%s' for address_category", name);
}

/**
 * idmef_address_category_to_string:
 * @val: an enumeration value for #idmef_address_category_t.
 *
 * Return the IDMEF string equivalent of @val provided #idmef_address_category_t value.
 *
 * Returns: a pointer to the string describing @val, or NULL if @val is invalid.
 */
const char *idmef_address_category_to_string(idmef_address_category_t val)
{
        const struct {
              idmef_address_category_t val;
              const char *name;
        } tbl[] = {
                { IDMEF_ADDRESS_CATEGORY_UNKNOWN, "unknown" },
                { IDMEF_ADDRESS_CATEGORY_ATM, "atm" },
                { IDMEF_ADDRESS_CATEGORY_E_MAIL, "e-mail" },
                { IDMEF_ADDRESS_CATEGORY_LOTUS_NOTES, "lotus-notes" },
                { IDMEF_ADDRESS_CATEGORY_MAC, "mac" },
                { IDMEF_ADDRESS_CATEGORY_SNA, "sna" },
                { IDMEF_ADDRESS_CATEGORY_VM, "vm" },
                { IDMEF_ADDRESS_CATEGORY_IPV4_ADDR, "ipv4-addr" },
                { IDMEF_ADDRESS_CATEGORY_IPV4_ADDR_HEX, "ipv4-addr-hex" },
                { IDMEF_ADDRESS_CATEGORY_IPV4_NET, "ipv4-net" },
                { IDMEF_ADDRESS_CATEGORY_IPV4_NET_MASK, "ipv4-net-mask" },
                { IDMEF_ADDRESS_CATEGORY_IPV6_ADDR, "ipv6-addr" },
                { IDMEF_ADDRESS_CATEGORY_IPV6_ADDR_HEX, "ipv6-addr-hex" },
                { IDMEF_ADDRESS_CATEGORY_IPV6_NET, "ipv6-net" },
                { IDMEF_ADDRESS_CATEGORY_IPV6_NET_MASK, "ipv6-net-mask" },
        };

        if ( val < 0 || (size_t) val >= (sizeof(tbl) / sizeof(*tbl)) )
                return NULL;

        return tbl[val].name;
}


struct idmef_address {
 
         IDMEF_LINKED_OBJECT;
         REFCOUNT;
         prelude_string_t *ident;
         idmef_address_category_t category;
         prelude_string_t *vlan_name;
         OPTIONAL_INT(int32_t, vlan_num);
         REQUIRED(prelude_string_t, *address);
         prelude_string_t *netmask;
 
};



struct idmef_process {
 
         IDMEF_OBJECT;
         REFCOUNT;
         prelude_string_t *ident;
         REQUIRED(prelude_string_t, *name);
         OPTIONAL_INT(uint32_t, pid);
         prelude_string_t *path;
 
         LISTED_OBJECT(arg_list, prelude_string_t);
         LISTED_OBJECT(env_list, prelude_string_t);
 
};



struct idmef_web_service {
 
         IDMEF_OBJECT;
         REFCOUNT;
         REQUIRED(prelude_string_t, *url);
         prelude_string_t *cgi;
         prelude_string_t *http_method;
         LISTED_OBJECT(arg_list, prelude_string_t);
 
};



struct idmef_snmp_service {
 
         IDMEF_OBJECT;
         REFCOUNT;
         prelude_string_t *oid;
         OPTIONAL_INT(uint32_t, message_processing_model);
         OPTIONAL_INT(uint32_t, security_model);
         prelude_string_t *security_name;
         OPTIONAL_INT(uint32_t, security_level);
         prelude_string_t *context_name;
         prelude_string_t *context_engine_id;
         prelude_string_t *command;
 
};


/**
 * idmef_service_type_to_numeric:
 * @name: pointer to an IDMEF string representation of a #idmef_service_type_t value.
 *
 * Returns: the numeric equivalent of @name, or -1 if @name is not valid.
 */
idmef_service_type_t idmef_service_type_to_numeric(const char *name)
{
        size_t i;
        const struct {
              idmef_service_type_t val;
              const char *name;
        } tbl[] = {
            { IDMEF_SERVICE_TYPE_DEFAULT, "default" },
            { IDMEF_SERVICE_TYPE_WEB, "web" },
            { IDMEF_SERVICE_TYPE_SNMP, "snmp" },
        };

        prelude_return_val_if_fail(name, prelude_error(PRELUDE_ERROR_ASSERTION));

        for ( i = 0; i < sizeof(tbl) / sizeof(*tbl); i++ ) {
                if ( strcasecmp(name, tbl[i].name) == 0 )
                        return tbl[i].val;
        }

        return prelude_error_verbose(PRELUDE_ERROR_IDMEF_UNKNOWN_ENUM_STRING, "Unknown enumeration value '%s' for service_type", name);
}

/**
 * idmef_service_type_to_string:
 * @val: an enumeration value for #idmef_service_type_t.
 *
 * Return the IDMEF string equivalent of @val provided #idmef_service_type_t value.
 *
 * Returns: a pointer to the string describing @val, or NULL if @val is invalid.
 */
const char *idmef_service_type_to_string(idmef_service_type_t val)
{
        const struct {
              idmef_service_type_t val;
              const char *name;
        } tbl[] = {
                { IDMEF_SERVICE_TYPE_DEFAULT, "default" },
                { IDMEF_SERVICE_TYPE_WEB, "web" },
                { IDMEF_SERVICE_TYPE_SNMP, "snmp" },
        };

        if ( val < 0 || (size_t) val >= (sizeof(tbl) / sizeof(*tbl)) )
                return NULL;

        return tbl[val].name;
}


struct idmef_service {
 
         IDMEF_OBJECT;
         REFCOUNT;
         prelude_string_t *ident;
 
         OPTIONAL_INT(uint8_t, ip_version);
         OPTIONAL_INT(uint8_t, iana_protocol_number);
         prelude_string_t *iana_protocol_name;
 
         prelude_string_t *name;
         OPTIONAL_INT(uint16_t, port);
         prelude_string_t *portlist;
         prelude_string_t *protocol;
 
         UNION(idmef_service_type_t, type) {
                 UNION_MEMBER(IDMEF_SERVICE_TYPE_WEB, idmef_web_service_t, *web_service);
                 UNION_MEMBER(IDMEF_SERVICE_TYPE_SNMP, idmef_snmp_service_t, *snmp_service);
         } specific;
 
 
};


/**
 * idmef_node_category_to_numeric:
 * @name: pointer to an IDMEF string representation of a #idmef_node_category_t value.
 *
 * Returns: the numeric equivalent of @name, or -1 if @name is not valid.
 */
idmef_node_category_t idmef_node_category_to_numeric(const char *name)
{
        size_t i;
        const struct {
              idmef_node_category_t val;
              const char *name;
        } tbl[] = {
            { IDMEF_NODE_CATEGORY_UNKNOWN, "unknown" },
            { IDMEF_NODE_CATEGORY_ADS, "ads" },
            { IDMEF_NODE_CATEGORY_AFS, "afs" },
            { IDMEF_NODE_CATEGORY_CODA, "coda" },
            { IDMEF_NODE_CATEGORY_DFS, "dfs" },
            { IDMEF_NODE_CATEGORY_DNS, "dns" },
            { IDMEF_NODE_CATEGORY_HOSTS, "hosts" },
            { IDMEF_NODE_CATEGORY_KERBEROS, "kerberos" },
            { IDMEF_NODE_CATEGORY_NDS, "nds" },
            { IDMEF_NODE_CATEGORY_NIS, "nis" },
            { IDMEF_NODE_CATEGORY_NISPLUS, "nisplus" },
            { IDMEF_NODE_CATEGORY_NT, "nt" },
            { IDMEF_NODE_CATEGORY_WFW, "wfw" },
        };

        prelude_return_val_if_fail(name, prelude_error(PRELUDE_ERROR_ASSERTION));

        for ( i = 0; i < sizeof(tbl) / sizeof(*tbl); i++ ) {
                if ( strcasecmp(name, tbl[i].name) == 0 )
                        return tbl[i].val;
        }

        return prelude_error_verbose(PRELUDE_ERROR_IDMEF_UNKNOWN_ENUM_STRING, "Unknown enumeration value '%s' for node_category", name);
}

/**
 * idmef_node_category_to_string:
 * @val: an enumeration value for #idmef_node_category_t.
 *
 * Return the IDMEF string equivalent of @val provided #idmef_node_category_t value.
 *
 * Returns: a pointer to the string describing @val, or NULL if @val is invalid.
 */
const char *idmef_node_category_to_string(idmef_node_category_t val)
{
        const struct {
              idmef_node_category_t val;
              const char *name;
        } tbl[] = {
                { IDMEF_NODE_CATEGORY_UNKNOWN, "unknown" },
                { IDMEF_NODE_CATEGORY_ADS, "ads" },
                { IDMEF_NODE_CATEGORY_AFS, "afs" },
                { IDMEF_NODE_CATEGORY_CODA, "coda" },
                { IDMEF_NODE_CATEGORY_DFS, "dfs" },
                { IDMEF_NODE_CATEGORY_DNS, "dns" },
                { IDMEF_NODE_CATEGORY_HOSTS, "hosts" },
                { IDMEF_NODE_CATEGORY_KERBEROS, "kerberos" },
                { IDMEF_NODE_CATEGORY_NDS, "nds" },
                { IDMEF_NODE_CATEGORY_NIS, "nis" },
                { IDMEF_NODE_CATEGORY_NISPLUS, "nisplus" },
                { IDMEF_NODE_CATEGORY_NT, "nt" },
                { IDMEF_NODE_CATEGORY_WFW, "wfw" },
        };

        if ( val < 0 || (size_t) val >= (sizeof(tbl) / sizeof(*tbl)) )
                return NULL;

        return tbl[val].name;
}


struct idmef_node {
 
         IDMEF_OBJECT;
         REFCOUNT;
         prelude_string_t *ident;
         idmef_node_category_t category;
         prelude_string_t *location;
         prelude_string_t *name;
         LISTED_OBJECT(address_list, idmef_address_t);
 
};


/**
 * idmef_source_spoofed_to_numeric:
 * @name: pointer to an IDMEF string representation of a #idmef_source_spoofed_t value.
 *
 * Returns: the numeric equivalent of @name, or -1 if @name is not valid.
 */
idmef_source_spoofed_t idmef_source_spoofed_to_numeric(const char *name)
{
        size_t i;
        const struct {
              idmef_source_spoofed_t val;
              const char *name;
        } tbl[] = {
            { IDMEF_SOURCE_SPOOFED_UNKNOWN, "unknown" },
            { IDMEF_SOURCE_SPOOFED_YES, "yes" },
            { IDMEF_SOURCE_SPOOFED_NO, "no" },
        };

        prelude_return_val_if_fail(name, prelude_error(PRELUDE_ERROR_ASSERTION));

        for ( i = 0; i < sizeof(tbl) / sizeof(*tbl); i++ ) {
                if ( strcasecmp(name, tbl[i].name) == 0 )
                        return tbl[i].val;
        }

        return prelude_error_verbose(PRELUDE_ERROR_IDMEF_UNKNOWN_ENUM_STRING, "Unknown enumeration value '%s' for source_spoofed", name);
}

/**
 * idmef_source_spoofed_to_string:
 * @val: an enumeration value for #idmef_source_spoofed_t.
 *
 * Return the IDMEF string equivalent of @val provided #idmef_source_spoofed_t value.
 *
 * Returns: a pointer to the string describing @val, or NULL if @val is invalid.
 */
const char *idmef_source_spoofed_to_string(idmef_source_spoofed_t val)
{
        const struct {
              idmef_source_spoofed_t val;
              const char *name;
        } tbl[] = {
                { IDMEF_SOURCE_SPOOFED_UNKNOWN, "unknown" },
                { IDMEF_SOURCE_SPOOFED_YES, "yes" },
                { IDMEF_SOURCE_SPOOFED_NO, "no" },
        };

        if ( val < 0 || (size_t) val >= (sizeof(tbl) / sizeof(*tbl)) )
                return NULL;

        return tbl[val].name;
}


struct idmef_source {
 
         IDMEF_LINKED_OBJECT;
         REFCOUNT;
         prelude_string_t *ident;
 
         idmef_source_spoofed_t spoofed;
         prelude_string_t *interface;
 
         idmef_node_t *node;
         idmef_user_t *user;
         idmef_process_t *process;
         idmef_service_t *service;
 
 
};



struct idmef_file_access {
 
         IDMEF_LINKED_OBJECT;
         REFCOUNT;
 
         REQUIRED(idmef_user_id_t, *user_id);
         LISTED_OBJECT(permission_list, prelude_string_t);
 
};



struct idmef_inode {
 
         IDMEF_OBJECT;
         REFCOUNT;
         idmef_time_t *change_time;
         OPTIONAL_INT(uint32_t, number);
         OPTIONAL_INT(uint32_t, major_device);
         OPTIONAL_INT(uint32_t, minor_device);
         OPTIONAL_INT(uint32_t, c_major_device);
         OPTIONAL_INT(uint32_t, c_minor_device);
 
};


/**
 * idmef_checksum_algorithm_to_numeric:
 * @name: pointer to an IDMEF string representation of a #idmef_checksum_algorithm_t value.
 *
 * Returns: the numeric equivalent of @name, or -1 if @name is not valid.
 */
idmef_checksum_algorithm_t idmef_checksum_algorithm_to_numeric(const char *name)
{
        size_t i;
        const struct {
              idmef_checksum_algorithm_t val;
              const char *name;
        } tbl[] = {
            { IDMEF_CHECKSUM_ALGORITHM_MD4, "MD4" },
            { IDMEF_CHECKSUM_ALGORITHM_MD5, "MD5" },
            { IDMEF_CHECKSUM_ALGORITHM_SHA1, "SHA1" },
            { IDMEF_CHECKSUM_ALGORITHM_SHA2_256, "SHA2-256" },
            { IDMEF_CHECKSUM_ALGORITHM_SHA2_384, "SHA2-384" },
            { IDMEF_CHECKSUM_ALGORITHM_SHA2_512, "SHA2-512" },
            { IDMEF_CHECKSUM_ALGORITHM_CRC_32, "CRC-32" },
            { IDMEF_CHECKSUM_ALGORITHM_HAVAL, "Haval" },
            { IDMEF_CHECKSUM_ALGORITHM_TIGER, "Tiger" },
            { IDMEF_CHECKSUM_ALGORITHM_GOST, "Gost" },
        };

        prelude_return_val_if_fail(name, prelude_error(PRELUDE_ERROR_ASSERTION));

        for ( i = 0; i < sizeof(tbl) / sizeof(*tbl); i++ ) {
                if ( strcasecmp(name, tbl[i].name) == 0 )
                        return tbl[i].val;
        }

        return prelude_error_verbose(PRELUDE_ERROR_IDMEF_UNKNOWN_ENUM_STRING, "Unknown enumeration value '%s' for checksum_algorithm", name);
}

/**
 * idmef_checksum_algorithm_to_string:
 * @val: an enumeration value for #idmef_checksum_algorithm_t.
 *
 * Return the IDMEF string equivalent of @val provided #idmef_checksum_algorithm_t value.
 *
 * Returns: a pointer to the string describing @val, or NULL if @val is invalid.
 */
const char *idmef_checksum_algorithm_to_string(idmef_checksum_algorithm_t val)
{
        const struct {
              idmef_checksum_algorithm_t val;
              const char *name;
        } tbl[] = {{ 0, NULL },
                { IDMEF_CHECKSUM_ALGORITHM_MD4, "MD4" },
                { IDMEF_CHECKSUM_ALGORITHM_MD5, "MD5" },
                { IDMEF_CHECKSUM_ALGORITHM_SHA1, "SHA1" },
                { IDMEF_CHECKSUM_ALGORITHM_SHA2_256, "SHA2-256" },
                { IDMEF_CHECKSUM_ALGORITHM_SHA2_384, "SHA2-384" },
                { IDMEF_CHECKSUM_ALGORITHM_SHA2_512, "SHA2-512" },
                { IDMEF_CHECKSUM_ALGORITHM_CRC_32, "CRC-32" },
                { IDMEF_CHECKSUM_ALGORITHM_HAVAL, "Haval" },
                { IDMEF_CHECKSUM_ALGORITHM_TIGER, "Tiger" },
                { IDMEF_CHECKSUM_ALGORITHM_GOST, "Gost" },
        };

        if ( val < 0 || (size_t) val >= (sizeof(tbl) / sizeof(*tbl)) )
                return NULL;

        return tbl[val].name;
}


struct idmef_checksum {
 
         IDMEF_LINKED_OBJECT;
         REFCOUNT;
         REQUIRED(prelude_string_t, *value);
         prelude_string_t *key;
         idmef_checksum_algorithm_t algorithm;
 
};


/**
 * idmef_file_category_to_numeric:
 * @name: pointer to an IDMEF string representation of a #idmef_file_category_t value.
 *
 * Returns: the numeric equivalent of @name, or -1 if @name is not valid.
 */
idmef_file_category_t idmef_file_category_to_numeric(const char *name)
{
        size_t i;
        const struct {
              idmef_file_category_t val;
              const char *name;
        } tbl[] = {
            { IDMEF_FILE_CATEGORY_CURRENT, "current" },
            { IDMEF_FILE_CATEGORY_ORIGINAL, "original" },
        };

        prelude_return_val_if_fail(name, prelude_error(PRELUDE_ERROR_ASSERTION));

        for ( i = 0; i < sizeof(tbl) / sizeof(*tbl); i++ ) {
                if ( strcasecmp(name, tbl[i].name) == 0 )
                        return tbl[i].val;
        }

        return prelude_error_verbose(PRELUDE_ERROR_IDMEF_UNKNOWN_ENUM_STRING, "Unknown enumeration value '%s' for file_category", name);
}

/**
 * idmef_file_category_to_string:
 * @val: an enumeration value for #idmef_file_category_t.
 *
 * Return the IDMEF string equivalent of @val provided #idmef_file_category_t value.
 *
 * Returns: a pointer to the string describing @val, or NULL if @val is invalid.
 */
const char *idmef_file_category_to_string(idmef_file_category_t val)
{
        const struct {
              idmef_file_category_t val;
              const char *name;
        } tbl[] = {{ 0, NULL },
                { IDMEF_FILE_CATEGORY_CURRENT, "current" },
                { IDMEF_FILE_CATEGORY_ORIGINAL, "original" },
        };

        if ( val < 0 || (size_t) val >= (sizeof(tbl) / sizeof(*tbl)) )
                return NULL;

        return tbl[val].name;
}

/**
 * idmef_file_fstype_to_numeric:
 * @name: pointer to an IDMEF string representation of a #idmef_file_fstype_t value.
 *
 * Returns: the numeric equivalent of @name, or -1 if @name is not valid.
 */
idmef_file_fstype_t idmef_file_fstype_to_numeric(const char *name)
{
        size_t i;
        const struct {
              idmef_file_fstype_t val;
              const char *name;
        } tbl[] = {
            { IDMEF_FILE_FSTYPE_UFS, "ufs" },
            { IDMEF_FILE_FSTYPE_EFS, "efs" },
            { IDMEF_FILE_FSTYPE_NFS, "nfs" },
            { IDMEF_FILE_FSTYPE_AFS, "afs" },
            { IDMEF_FILE_FSTYPE_NTFS, "ntfs" },
            { IDMEF_FILE_FSTYPE_FAT16, "fat16" },
            { IDMEF_FILE_FSTYPE_FAT32, "fat32" },
            { IDMEF_FILE_FSTYPE_PCFS, "pcfs" },
            { IDMEF_FILE_FSTYPE_JOLIET, "joliet" },
            { IDMEF_FILE_FSTYPE_ISO9660, "iso9660" },
        };

        prelude_return_val_if_fail(name, prelude_error(PRELUDE_ERROR_ASSERTION));

        for ( i = 0; i < sizeof(tbl) / sizeof(*tbl); i++ ) {
                if ( strcasecmp(name, tbl[i].name) == 0 )
                        return tbl[i].val;
        }

        return prelude_error_verbose(PRELUDE_ERROR_IDMEF_UNKNOWN_ENUM_STRING, "Unknown enumeration value '%s' for file_fstype", name);
}

/**
 * idmef_file_fstype_to_string:
 * @val: an enumeration value for #idmef_file_fstype_t.
 *
 * Return the IDMEF string equivalent of @val provided #idmef_file_fstype_t value.
 *
 * Returns: a pointer to the string describing @val, or NULL if @val is invalid.
 */
const char *idmef_file_fstype_to_string(idmef_file_fstype_t val)
{
        const struct {
              idmef_file_fstype_t val;
              const char *name;
        } tbl[] = {{ 0, NULL },
                { IDMEF_FILE_FSTYPE_UFS, "ufs" },
                { IDMEF_FILE_FSTYPE_EFS, "efs" },
                { IDMEF_FILE_FSTYPE_NFS, "nfs" },
                { IDMEF_FILE_FSTYPE_AFS, "afs" },
                { IDMEF_FILE_FSTYPE_NTFS, "ntfs" },
                { IDMEF_FILE_FSTYPE_FAT16, "fat16" },
                { IDMEF_FILE_FSTYPE_FAT32, "fat32" },
                { IDMEF_FILE_FSTYPE_PCFS, "pcfs" },
                { IDMEF_FILE_FSTYPE_JOLIET, "joliet" },
                { IDMEF_FILE_FSTYPE_ISO9660, "iso9660" },
        };

        if ( val < 0 || (size_t) val >= (sizeof(tbl) / sizeof(*tbl)) )
                return NULL;

        return tbl[val].name;
}


struct idmef_file {
 
         IDMEF_LINKED_OBJECT;
         REFCOUNT;
         prelude_string_t *ident;
 
         REQUIRED(prelude_string_t, *name);
         REQUIRED(prelude_string_t, *path);
 
         idmef_time_t *create_time;
         idmef_time_t *modify_time;
         idmef_time_t *access_time;
 
 
         OPTIONAL_INT(uint64_t, data_size);
         OPTIONAL_INT(uint64_t, disk_size);
 
         LISTED_OBJECT(file_access_list, idmef_file_access_t);
         LISTED_OBJECT(linkage_list, idmef_linkage_t);
 
         idmef_inode_t *inode;
         LISTED_OBJECT(checksum_list, idmef_checksum_t);
 
         idmef_file_category_t category;
         OPTIONAL_INT(idmef_file_fstype_t, fstype);
         prelude_string_t *file_type;
 
 
};


/**
 * idmef_linkage_category_to_numeric:
 * @name: pointer to an IDMEF string representation of a #idmef_linkage_category_t value.
 *
 * Returns: the numeric equivalent of @name, or -1 if @name is not valid.
 */
idmef_linkage_category_t idmef_linkage_category_to_numeric(const char *name)
{
        size_t i;
        const struct {
              idmef_linkage_category_t val;
              const char *name;
        } tbl[] = {
            { IDMEF_LINKAGE_CATEGORY_HARD_LINK, "hard-link" },
            { IDMEF_LINKAGE_CATEGORY_MOUNT_POINT, "mount-point" },
            { IDMEF_LINKAGE_CATEGORY_REPARSE_POINT, "reparse-point" },
            { IDMEF_LINKAGE_CATEGORY_SHORTCUT, "shortcut" },
            { IDMEF_LINKAGE_CATEGORY_STREAM, "stream" },
            { IDMEF_LINKAGE_CATEGORY_SYMBOLIC_LINK, "symbolic-link" },
        };

        prelude_return_val_if_fail(name, prelude_error(PRELUDE_ERROR_ASSERTION));

        for ( i = 0; i < sizeof(tbl) / sizeof(*tbl); i++ ) {
                if ( strcasecmp(name, tbl[i].name) == 0 )
                        return tbl[i].val;
        }

        return prelude_error_verbose(PRELUDE_ERROR_IDMEF_UNKNOWN_ENUM_STRING, "Unknown enumeration value '%s' for linkage_category", name);
}

/**
 * idmef_linkage_category_to_string:
 * @val: an enumeration value for #idmef_linkage_category_t.
 *
 * Return the IDMEF string equivalent of @val provided #idmef_linkage_category_t value.
 *
 * Returns: a pointer to the string describing @val, or NULL if @val is invalid.
 */
const char *idmef_linkage_category_to_string(idmef_linkage_category_t val)
{
        const struct {
              idmef_linkage_category_t val;
              const char *name;
        } tbl[] = {{ 0, NULL },
                { IDMEF_LINKAGE_CATEGORY_HARD_LINK, "hard-link" },
                { IDMEF_LINKAGE_CATEGORY_MOUNT_POINT, "mount-point" },
                { IDMEF_LINKAGE_CATEGORY_REPARSE_POINT, "reparse-point" },
                { IDMEF_LINKAGE_CATEGORY_SHORTCUT, "shortcut" },
                { IDMEF_LINKAGE_CATEGORY_STREAM, "stream" },
                { IDMEF_LINKAGE_CATEGORY_SYMBOLIC_LINK, "symbolic-link" },
        };

        if ( val < 0 || (size_t) val >= (sizeof(tbl) / sizeof(*tbl)) )
                return NULL;

        return tbl[val].name;
}


struct idmef_linkage {
 
         IDMEF_LINKED_OBJECT;
         REFCOUNT;
 
         idmef_linkage_category_t category;
         REQUIRED(prelude_string_t, *name);
         REQUIRED(prelude_string_t, *path);
         REQUIRED(idmef_file_t, *file);
 
};


/**
 * idmef_target_decoy_to_numeric:
 * @name: pointer to an IDMEF string representation of a #idmef_target_decoy_t value.
 *
 * Returns: the numeric equivalent of @name, or -1 if @name is not valid.
 */
idmef_target_decoy_t idmef_target_decoy_to_numeric(const char *name)
{
        size_t i;
        const struct {
              idmef_target_decoy_t val;
              const char *name;
        } tbl[] = {
            { IDMEF_TARGET_DECOY_UNKNOWN, "unknown" },
            { IDMEF_TARGET_DECOY_YES, "yes" },
            { IDMEF_TARGET_DECOY_NO, "no" },
        };

        prelude_return_val_if_fail(name, prelude_error(PRELUDE_ERROR_ASSERTION));

        for ( i = 0; i < sizeof(tbl) / sizeof(*tbl); i++ ) {
                if ( strcasecmp(name, tbl[i].name) == 0 )
                        return tbl[i].val;
        }

        return prelude_error_verbose(PRELUDE_ERROR_IDMEF_UNKNOWN_ENUM_STRING, "Unknown enumeration value '%s' for target_decoy", name);
}

/**
 * idmef_target_decoy_to_string:
 * @val: an enumeration value for #idmef_target_decoy_t.
 *
 * Return the IDMEF string equivalent of @val provided #idmef_target_decoy_t value.
 *
 * Returns: a pointer to the string describing @val, or NULL if @val is invalid.
 */
const char *idmef_target_decoy_to_string(idmef_target_decoy_t val)
{
        const struct {
              idmef_target_decoy_t val;
              const char *name;
        } tbl[] = {
                { IDMEF_TARGET_DECOY_UNKNOWN, "unknown" },
                { IDMEF_TARGET_DECOY_YES, "yes" },
                { IDMEF_TARGET_DECOY_NO, "no" },
        };

        if ( val < 0 || (size_t) val >= (sizeof(tbl) / sizeof(*tbl)) )
                return NULL;

        return tbl[val].name;
}


struct idmef_target {
 
         IDMEF_LINKED_OBJECT;
         REFCOUNT;
         prelude_string_t *ident;
 
         idmef_target_decoy_t decoy;
         prelude_string_t *interface;
 
         idmef_node_t *node;
         idmef_user_t *user;
         idmef_process_t *process;
         idmef_service_t *service;
         LISTED_OBJECT(file_list, idmef_file_t);
 
};



struct idmef_analyzer {
 
         IDMEF_LINKED_OBJECT;
         REFCOUNT;
         prelude_string_t *analyzerid;
 
         prelude_string_t *name;
         prelude_string_t *manufacturer;
         prelude_string_t *model;
         prelude_string_t *version;
         prelude_string_t *class;
         prelude_string_t *ostype;
         prelude_string_t *osversion;
 
         idmef_node_t *node;
         idmef_process_t *process;
 
 
};



struct idmef_alertident {
 
         IDMEF_LINKED_OBJECT;
         REFCOUNT;
 
         REQUIRED(prelude_string_t, *alertident);
         prelude_string_t *analyzerid;
 
 
};


/**
 * idmef_impact_severity_to_numeric:
 * @name: pointer to an IDMEF string representation of a #idmef_impact_severity_t value.
 *
 * Returns: the numeric equivalent of @name, or -1 if @name is not valid.
 */
idmef_impact_severity_t idmef_impact_severity_to_numeric(const char *name)
{
        size_t i;
        const struct {
              idmef_impact_severity_t val;
              const char *name;
        } tbl[] = {
            { IDMEF_IMPACT_SEVERITY_INFO, "info" },
            { IDMEF_IMPACT_SEVERITY_LOW, "low" },
            { IDMEF_IMPACT_SEVERITY_MEDIUM, "medium" },
            { IDMEF_IMPACT_SEVERITY_HIGH, "high" },
        };

        prelude_return_val_if_fail(name, prelude_error(PRELUDE_ERROR_ASSERTION));

        for ( i = 0; i < sizeof(tbl) / sizeof(*tbl); i++ ) {
                if ( strcasecmp(name, tbl[i].name) == 0 )
                        return tbl[i].val;
        }

        return prelude_error_verbose(PRELUDE_ERROR_IDMEF_UNKNOWN_ENUM_STRING, "Unknown enumeration value '%s' for impact_severity", name);
}

/**
 * idmef_impact_severity_to_string:
 * @val: an enumeration value for #idmef_impact_severity_t.
 *
 * Return the IDMEF string equivalent of @val provided #idmef_impact_severity_t value.
 *
 * Returns: a pointer to the string describing @val, or NULL if @val is invalid.
 */
const char *idmef_impact_severity_to_string(idmef_impact_severity_t val)
{
        const struct {
              idmef_impact_severity_t val;
              const char *name;
        } tbl[] = {{ 0, NULL },
                { IDMEF_IMPACT_SEVERITY_INFO, "info" },
                { IDMEF_IMPACT_SEVERITY_LOW, "low" },
                { IDMEF_IMPACT_SEVERITY_MEDIUM, "medium" },
                { IDMEF_IMPACT_SEVERITY_HIGH, "high" },
        };

        if ( val < 0 || (size_t) val >= (sizeof(tbl) / sizeof(*tbl)) )
                return NULL;

        return tbl[val].name;
}

/**
 * idmef_impact_completion_to_numeric:
 * @name: pointer to an IDMEF string representation of a #idmef_impact_completion_t value.
 *
 * Returns: the numeric equivalent of @name, or -1 if @name is not valid.
 */
idmef_impact_completion_t idmef_impact_completion_to_numeric(const char *name)
{
        size_t i;
        const struct {
              idmef_impact_completion_t val;
              const char *name;
        } tbl[] = {
            { IDMEF_IMPACT_COMPLETION_FAILED, "failed" },
            { IDMEF_IMPACT_COMPLETION_SUCCEEDED, "succeeded" },
        };

        prelude_return_val_if_fail(name, prelude_error(PRELUDE_ERROR_ASSERTION));

        for ( i = 0; i < sizeof(tbl) / sizeof(*tbl); i++ ) {
                if ( strcasecmp(name, tbl[i].name) == 0 )
                        return tbl[i].val;
        }

        return prelude_error_verbose(PRELUDE_ERROR_IDMEF_UNKNOWN_ENUM_STRING, "Unknown enumeration value '%s' for impact_completion", name);
}

/**
 * idmef_impact_completion_to_string:
 * @val: an enumeration value for #idmef_impact_completion_t.
 *
 * Return the IDMEF string equivalent of @val provided #idmef_impact_completion_t value.
 *
 * Returns: a pointer to the string describing @val, or NULL if @val is invalid.
 */
const char *idmef_impact_completion_to_string(idmef_impact_completion_t val)
{
        const struct {
              idmef_impact_completion_t val;
              const char *name;
        } tbl[] = {{ 0, NULL },
                { IDMEF_IMPACT_COMPLETION_FAILED, "failed" },
                { IDMEF_IMPACT_COMPLETION_SUCCEEDED, "succeeded" },
        };

        if ( val < 0 || (size_t) val >= (sizeof(tbl) / sizeof(*tbl)) )
                return NULL;

        return tbl[val].name;
}

/**
 * idmef_impact_type_to_numeric:
 * @name: pointer to an IDMEF string representation of a #idmef_impact_type_t value.
 *
 * Returns: the numeric equivalent of @name, or -1 if @name is not valid.
 */
idmef_impact_type_t idmef_impact_type_to_numeric(const char *name)
{
        size_t i;
        const struct {
              idmef_impact_type_t val;
              const char *name;
        } tbl[] = {
            { IDMEF_IMPACT_TYPE_OTHER, "other" },
            { IDMEF_IMPACT_TYPE_ADMIN, "admin" },
            { IDMEF_IMPACT_TYPE_DOS, "dos" },
            { IDMEF_IMPACT_TYPE_FILE, "file" },
            { IDMEF_IMPACT_TYPE_RECON, "recon" },
            { IDMEF_IMPACT_TYPE_USER, "user" },
        };

        prelude_return_val_if_fail(name, prelude_error(PRELUDE_ERROR_ASSERTION));

        for ( i = 0; i < sizeof(tbl) / sizeof(*tbl); i++ ) {
                if ( strcasecmp(name, tbl[i].name) == 0 )
                        return tbl[i].val;
        }

        return prelude_error_verbose(PRELUDE_ERROR_IDMEF_UNKNOWN_ENUM_STRING, "Unknown enumeration value '%s' for impact_type", name);
}

/**
 * idmef_impact_type_to_string:
 * @val: an enumeration value for #idmef_impact_type_t.
 *
 * Return the IDMEF string equivalent of @val provided #idmef_impact_type_t value.
 *
 * Returns: a pointer to the string describing @val, or NULL if @val is invalid.
 */
const char *idmef_impact_type_to_string(idmef_impact_type_t val)
{
        const struct {
              idmef_impact_type_t val;
              const char *name;
        } tbl[] = {
                { IDMEF_IMPACT_TYPE_OTHER, "other" },
                { IDMEF_IMPACT_TYPE_ADMIN, "admin" },
                { IDMEF_IMPACT_TYPE_DOS, "dos" },
                { IDMEF_IMPACT_TYPE_FILE, "file" },
                { IDMEF_IMPACT_TYPE_RECON, "recon" },
                { IDMEF_IMPACT_TYPE_USER, "user" },
        };

        if ( val < 0 || (size_t) val >= (sizeof(tbl) / sizeof(*tbl)) )
                return NULL;

        return tbl[val].name;
}


struct idmef_impact {
 
         IDMEF_OBJECT;
         REFCOUNT;
 
         OPTIONAL_INT(idmef_impact_severity_t, severity);
         OPTIONAL_INT(idmef_impact_completion_t, completion);
         idmef_impact_type_t type;
         prelude_string_t *description;
 
};


/**
 * idmef_action_category_to_numeric:
 * @name: pointer to an IDMEF string representation of a #idmef_action_category_t value.
 *
 * Returns: the numeric equivalent of @name, or -1 if @name is not valid.
 */
idmef_action_category_t idmef_action_category_to_numeric(const char *name)
{
        size_t i;
        const struct {
              idmef_action_category_t val;
              const char *name;
        } tbl[] = {
            { IDMEF_ACTION_CATEGORY_OTHER, "other" },
            { IDMEF_ACTION_CATEGORY_BLOCK_INSTALLED, "block-installed" },
            { IDMEF_ACTION_CATEGORY_NOTIFICATION_SENT, "notification-sent" },
            { IDMEF_ACTION_CATEGORY_TAKEN_OFFLINE, "taken-offline" },
        };

        prelude_return_val_if_fail(name, prelude_error(PRELUDE_ERROR_ASSERTION));

        for ( i = 0; i < sizeof(tbl) / sizeof(*tbl); i++ ) {
                if ( strcasecmp(name, tbl[i].name) == 0 )
                        return tbl[i].val;
        }

        return prelude_error_verbose(PRELUDE_ERROR_IDMEF_UNKNOWN_ENUM_STRING, "Unknown enumeration value '%s' for action_category", name);
}

/**
 * idmef_action_category_to_string:
 * @val: an enumeration value for #idmef_action_category_t.
 *
 * Return the IDMEF string equivalent of @val provided #idmef_action_category_t value.
 *
 * Returns: a pointer to the string describing @val, or NULL if @val is invalid.
 */
const char *idmef_action_category_to_string(idmef_action_category_t val)
{
        const struct {
              idmef_action_category_t val;
              const char *name;
        } tbl[] = {
                { IDMEF_ACTION_CATEGORY_OTHER, "other" },
                { IDMEF_ACTION_CATEGORY_BLOCK_INSTALLED, "block-installed" },
                { IDMEF_ACTION_CATEGORY_NOTIFICATION_SENT, "notification-sent" },
                { IDMEF_ACTION_CATEGORY_TAKEN_OFFLINE, "taken-offline" },
        };

        if ( val < 0 || (size_t) val >= (sizeof(tbl) / sizeof(*tbl)) )
                return NULL;

        return tbl[val].name;
}


struct idmef_action {
 
         IDMEF_LINKED_OBJECT;
         REFCOUNT;
 
         idmef_action_category_t category;
         prelude_string_t *description;
 
};


/**
 * idmef_confidence_rating_to_numeric:
 * @name: pointer to an IDMEF string representation of a #idmef_confidence_rating_t value.
 *
 * Returns: the numeric equivalent of @name, or -1 if @name is not valid.
 */
idmef_confidence_rating_t idmef_confidence_rating_to_numeric(const char *name)
{
        size_t i;
        const struct {
              idmef_confidence_rating_t val;
              const char *name;
        } tbl[] = {
            { IDMEF_CONFIDENCE_RATING_NUMERIC, "numeric" },
            { IDMEF_CONFIDENCE_RATING_LOW, "low" },
            { IDMEF_CONFIDENCE_RATING_MEDIUM, "medium" },
            { IDMEF_CONFIDENCE_RATING_HIGH, "high" },
        };

        prelude_return_val_if_fail(name, prelude_error(PRELUDE_ERROR_ASSERTION));

        for ( i = 0; i < sizeof(tbl) / sizeof(*tbl); i++ ) {
                if ( strcasecmp(name, tbl[i].name) == 0 )
                        return tbl[i].val;
        }

        return prelude_error_verbose(PRELUDE_ERROR_IDMEF_UNKNOWN_ENUM_STRING, "Unknown enumeration value '%s' for confidence_rating", name);
}

/**
 * idmef_confidence_rating_to_string:
 * @val: an enumeration value for #idmef_confidence_rating_t.
 *
 * Return the IDMEF string equivalent of @val provided #idmef_confidence_rating_t value.
 *
 * Returns: a pointer to the string describing @val, or NULL if @val is invalid.
 */
const char *idmef_confidence_rating_to_string(idmef_confidence_rating_t val)
{
        const struct {
              idmef_confidence_rating_t val;
              const char *name;
        } tbl[] = {
                { IDMEF_CONFIDENCE_RATING_NUMERIC, "numeric" },
                { IDMEF_CONFIDENCE_RATING_LOW, "low" },
                { IDMEF_CONFIDENCE_RATING_MEDIUM, "medium" },
                { IDMEF_CONFIDENCE_RATING_HIGH, "high" },
        };

        if ( val < 0 || (size_t) val >= (sizeof(tbl) / sizeof(*tbl)) )
                return NULL;

        return tbl[val].name;
}


struct idmef_confidence {
 
         IDMEF_OBJECT;
         REFCOUNT;
 
         idmef_confidence_rating_t rating;
         float confidence;
 
};



struct idmef_assessment {
 
         IDMEF_OBJECT;
         REFCOUNT;
 
         idmef_impact_t *impact;
         LISTED_OBJECT(action_list, idmef_action_t);
         idmef_confidence_t *confidence;
 
};



struct idmef_tool_alert {
 
         IDMEF_OBJECT;
         REFCOUNT;
 
         REQUIRED(prelude_string_t, *name);
         prelude_string_t *command;
         LISTED_OBJECT(alertident_list, idmef_alertident_t);
 
};



struct idmef_correlation_alert {
 
         IDMEF_OBJECT;
         REFCOUNT;
 
         REQUIRED(prelude_string_t, *name);
         LISTED_OBJECT(alertident_list, idmef_alertident_t);
 
};



struct idmef_overflow_alert {
 
         IDMEF_OBJECT;
         REFCOUNT;
 
         REQUIRED(prelude_string_t, *program);
         OPTIONAL_INT(uint32_t, size);
         idmef_data_t *buffer;
 
};


/**
 * idmef_alert_type_to_numeric:
 * @name: pointer to an IDMEF string representation of a #idmef_alert_type_t value.
 *
 * Returns: the numeric equivalent of @name, or -1 if @name is not valid.
 */
idmef_alert_type_t idmef_alert_type_to_numeric(const char *name)
{
        size_t i;
        const struct {
              idmef_alert_type_t val;
              const char *name;
        } tbl[] = {
            { IDMEF_ALERT_TYPE_DEFAULT, "default" },
            { IDMEF_ALERT_TYPE_TOOL, "tool" },
            { IDMEF_ALERT_TYPE_CORRELATION, "correlation" },
            { IDMEF_ALERT_TYPE_OVERFLOW, "overflow" },
        };

        prelude_return_val_if_fail(name, prelude_error(PRELUDE_ERROR_ASSERTION));

        for ( i = 0; i < sizeof(tbl) / sizeof(*tbl); i++ ) {
                if ( strcasecmp(name, tbl[i].name) == 0 )
                        return tbl[i].val;
        }

        return prelude_error_verbose(PRELUDE_ERROR_IDMEF_UNKNOWN_ENUM_STRING, "Unknown enumeration value '%s' for alert_type", name);
}

/**
 * idmef_alert_type_to_string:
 * @val: an enumeration value for #idmef_alert_type_t.
 *
 * Return the IDMEF string equivalent of @val provided #idmef_alert_type_t value.
 *
 * Returns: a pointer to the string describing @val, or NULL if @val is invalid.
 */
const char *idmef_alert_type_to_string(idmef_alert_type_t val)
{
        const struct {
              idmef_alert_type_t val;
              const char *name;
        } tbl[] = {
                { IDMEF_ALERT_TYPE_DEFAULT, "default" },
                { IDMEF_ALERT_TYPE_TOOL, "tool" },
                { IDMEF_ALERT_TYPE_CORRELATION, "correlation" },
                { IDMEF_ALERT_TYPE_OVERFLOW, "overflow" },
        };

        if ( val < 0 || (size_t) val >= (sizeof(tbl) / sizeof(*tbl)) )
                return NULL;

        return tbl[val].name;
}


struct idmef_alert {
 
         IDMEF_OBJECT;
         REFCOUNT;
         prelude_string_t *messageid;
 
         LISTED_OBJECT(analyzer_list, idmef_analyzer_t);
 
         REQUIRED(idmef_time_t, *create_time);
         REQUIRED(idmef_classification_t, *classification);
         idmef_time_t *detect_time;
         idmef_time_t *analyzer_time;
 
         LISTED_OBJECT(source_list, idmef_source_t);
         LISTED_OBJECT(target_list, idmef_target_t);
 
         idmef_assessment_t *assessment;
 
         KEYLISTED_OBJECT(additional_data_list, idmef_additional_data_t);
 
         UNION(idmef_alert_type_t, type) {
                 UNION_MEMBER(IDMEF_ALERT_TYPE_TOOL, idmef_tool_alert_t, *tool_alert);
                 UNION_MEMBER(IDMEF_ALERT_TYPE_CORRELATION, idmef_correlation_alert_t, *correlation_alert);
                 UNION_MEMBER(IDMEF_ALERT_TYPE_OVERFLOW, idmef_overflow_alert_t, *overflow_alert);
         } detail;
 
 
};



struct idmef_heartbeat {
 
         IDMEF_OBJECT;
         REFCOUNT;
 
         prelude_string_t *messageid;
         LISTED_OBJECT(analyzer_list, idmef_analyzer_t);
 
         REQUIRED(idmef_time_t, *create_time);
         idmef_time_t *analyzer_time;
 
         OPTIONAL_INT(uint32_t, heartbeat_interval);
         KEYLISTED_OBJECT(additional_data_list, idmef_additional_data_t);
 
};


/**
 * idmef_message_type_to_numeric:
 * @name: pointer to an IDMEF string representation of a #idmef_message_type_t value.
 *
 * Returns: the numeric equivalent of @name, or -1 if @name is not valid.
 */
idmef_message_type_t idmef_message_type_to_numeric(const char *name)
{
        size_t i;
        const struct {
              idmef_message_type_t val;
              const char *name;
        } tbl[] = {
            { IDMEF_MESSAGE_TYPE_ALERT, "alert" },
            { IDMEF_MESSAGE_TYPE_HEARTBEAT, "heartbeat" },
        };

        prelude_return_val_if_fail(name, prelude_error(PRELUDE_ERROR_ASSERTION));

        for ( i = 0; i < sizeof(tbl) / sizeof(*tbl); i++ ) {
                if ( strcasecmp(name, tbl[i].name) == 0 )
                        return tbl[i].val;
        }

        return prelude_error_verbose(PRELUDE_ERROR_IDMEF_UNKNOWN_ENUM_STRING, "Unknown enumeration value '%s' for message_type", name);
}

/**
 * idmef_message_type_to_string:
 * @val: an enumeration value for #idmef_message_type_t.
 *
 * Return the IDMEF string equivalent of @val provided #idmef_message_type_t value.
 *
 * Returns: a pointer to the string describing @val, or NULL if @val is invalid.
 */
const char *idmef_message_type_to_string(idmef_message_type_t val)
{
        const struct {
              idmef_message_type_t val;
              const char *name;
        } tbl[] = {{ 0, NULL },
                { IDMEF_MESSAGE_TYPE_ALERT, "alert" },
                { IDMEF_MESSAGE_TYPE_HEARTBEAT, "heartbeat" },
        };

        if ( val < 0 || (size_t) val >= (sizeof(tbl) / sizeof(*tbl)) )
                return NULL;

        return tbl[val].name;
}


struct idmef_message {
 
         IDMEF_OBJECT;
         REFCOUNT;
 
         REQUIRED(prelude_string_t, *version);
 
         UNION(idmef_message_type_t, type) {
                 UNION_MEMBER(IDMEF_MESSAGE_TYPE_ALERT, idmef_alert_t, *alert);
                 UNION_MEMBER(IDMEF_MESSAGE_TYPE_HEARTBEAT, idmef_heartbeat_t, *heartbeat);
         } message;
 
         HIDE(prelude_msg_t *, pmsg);
 
 
};


/**
 * idmef_additional_data_new:
 * @ret: Pointer where to store the created #idmef_additional_data_t object.
 *
 * Create a new #idmef_additional_data_t object.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_additional_data_new(idmef_additional_data_t **ret)
{
        *ret = calloc(1, sizeof(**ret));
        if ( ! *ret )
                return prelude_error_from_errno(errno);

        (*ret)->_idmef_object_id = IDMEF_CLASS_ID_ADDITIONAL_DATA;

        prelude_list_init(&((prelude_linked_object_t *) (*ret))->_list);

        (*ret)->refcount = 1;

        {
                int retval = idmef_data_new(&(*ret)->data);

                if ( retval < 0 ) {
                        idmef_additional_data_destroy(*ret);
                        *ret = NULL;
                        return retval;
                }
        }

        return 0;

}

/**
 * idmef_additional_data_ref:
 * @additional_data: pointer to a #idmef_additional_data_t object.
 *
 * Increase @additional_data reference count, so that it can be referenced
 * multiple time.
 *
 * Returns: a pointer to @additional_data.
 */
idmef_additional_data_t *idmef_additional_data_ref(idmef_additional_data_t *additional_data)
{
        prelude_return_val_if_fail(additional_data, NULL);
        additional_data->refcount++;

        return additional_data;
}

int _idmef_additional_data_get_child(void *p, idmef_class_child_id_t child, void **childptr)
{
        idmef_additional_data_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));
        *childptr = NULL;

        switch ( child ) {

                case 0:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->meaning, TRUE);
                case 1:
                       return idmef_value_new_enum_from_numeric((idmef_value_t **) childptr,
                                                                IDMEF_CLASS_ID_ADDITIONAL_DATA_TYPE, ptr->type);

                case 2:
                       return get_value_from_data((idmef_value_t **) childptr,  ptr->data, TRUE);
                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_additional_data_new_child(void *p, idmef_class_child_id_t child, int n, void **ret)
{
        idmef_additional_data_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        return idmef_additional_data_new_meaning(ptr, (prelude_string_t **) ret);

                case 1:
                        return idmef_additional_data_new_type(ptr, (idmef_additional_data_type_t **) ret);

                case 2:
                        return idmef_additional_data_new_data(ptr, (idmef_data_t **) ret);

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_additional_data_destroy_child(void *p, idmef_class_child_id_t child, int n)
{
        idmef_additional_data_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        if ( ptr->meaning ) {
                                prelude_string_destroy(ptr->meaning);
                                ptr->meaning = NULL;
                        }

                        return 0;

                case 1:
                        ptr->type = 0;
                        return 0;

                case 2:
                        if ( ptr->data ) {
                                idmef_data_destroy(ptr->data);
                                ptr->data = NULL;
                        }

                        return 0;

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

static void idmef_additional_data_destroy_internal(idmef_additional_data_t *ptr)
{
        prelude_return_if_fail(ptr);

       if ( ! prelude_list_is_empty(&((prelude_linked_object_t *)ptr)->_list) )
               prelude_list_del_init(&((prelude_linked_object_t *)ptr)->_list);
    
        if ( ptr->meaning ) {
                prelude_string_destroy(ptr->meaning);
                ptr->meaning = NULL;
        }

        if ( ptr->data ) {
                idmef_data_destroy(ptr->data);
                ptr->data = NULL;
        }


        /* free() should be done by the caller */
}

/**
 * idmef_additional_data_destroy:
 * @ptr: pointer to a #idmef_additional_data_t object.
 *
 * Destroy @ptr and all of it's children.
 * The objects are only destroyed if their reference count reach zero.
 */

void idmef_additional_data_destroy(idmef_additional_data_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( --ptr->refcount )
                return;

        idmef_additional_data_destroy_internal(ptr);
        free(ptr);
}

/**
 * idmef_additional_data_get_meaning:
 * @ptr: pointer to a #idmef_additional_data_t object.
 *
 * Get meaning children of the #idmef_additional_data_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_additional_data_get_meaning(idmef_additional_data_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->meaning;
}

/**
 * idmef_additional_data_set_meaning:
 * @ptr: pointer to a #idmef_additional_data_t object.
 * @meaning: pointer to a #prelude_string_t object.
 *
 * Set @meaning object as a children of @ptr.
 * if @ptr already contain an @meaning object, then it is destroyed,
 * and updated to point to the provided @meaning object.
 */

void idmef_additional_data_set_meaning(idmef_additional_data_t *ptr, prelude_string_t *meaning)
{
        prelude_return_if_fail(ptr);

        if ( ptr->meaning )
                prelude_string_destroy(ptr->meaning);

        ptr->meaning = meaning;
}

/**
 * idmef_additional_data_new_meaning:
 * @ptr: pointer to a #idmef_additional_data_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new meaning object, children of #idmef_additional_data_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_additional_data_new_meaning(idmef_additional_data_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->meaning ) {
                retval = prelude_string_new(&ptr->meaning);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->meaning;
        return 0;
}

/**
 * idmef_additional_data_get_type:
 * @ptr: pointer to a #idmef_additional_data_t object.
 *
 * Get type children of the #idmef_additional_data_t object.
 *
 * Returns: a pointer to a idmef_additional_data_type_t object, or NULL if the children object is not set.
 */
idmef_additional_data_type_t idmef_additional_data_get_type(idmef_additional_data_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->type;
}

/**
 * idmef_additional_data_set_type:
 * @ptr: pointer to a #idmef_additional_data_t object.
 * @type: pointer to a #idmef_additional_data_type_t object.
 *
 * Set @type object as a children of @ptr.
 * if @ptr already contain an @type object, then it is destroyed,
 * and updated to point to the provided @type object.
 */

void idmef_additional_data_set_type(idmef_additional_data_t *ptr, idmef_additional_data_type_t type)
{
        prelude_return_if_fail(ptr);
        ptr->type = type;

        ptr->_type_is_set = TRUE;

}

/**
 * idmef_additional_data_new_type:
 * @ptr: pointer to a #idmef_additional_data_t object.
 * @ret: pointer to an address where to store the created #idmef_additional_data_type_t object.
 *
 * Create a new type object, children of #idmef_additional_data_t.
 * If @ptr already contain a #idmef_additional_data_type_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_additional_data_new_type(idmef_additional_data_t *ptr, idmef_additional_data_type_t **ret)
{
        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));
        ptr->_type_is_set = TRUE;
        *ret = &ptr->type;
        return 0;
}

/**
 * idmef_additional_data_get_data:
 * @ptr: pointer to a #idmef_additional_data_t object.
 *
 * Get data children of the #idmef_additional_data_t object.
 *
 * Returns: a pointer to a idmef_data_t object, or NULL if the children object is not set.
 */
idmef_data_t *idmef_additional_data_get_data(idmef_additional_data_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->data;
}

/**
 * idmef_additional_data_set_data:
 * @ptr: pointer to a #idmef_additional_data_t object.
 * @data: pointer to a #idmef_data_t object.
 *
 * Set @data object as a children of @ptr.
 * if @ptr already contain an @data object, then it is destroyed,
 * and updated to point to the provided @data object.
 */

void idmef_additional_data_set_data(idmef_additional_data_t *ptr, idmef_data_t *data)
{
        prelude_return_if_fail(ptr);

        if ( ptr->data )
                idmef_data_destroy(ptr->data);

        ptr->data = data;
}

/**
 * idmef_additional_data_new_data:
 * @ptr: pointer to a #idmef_additional_data_t object.
 * @ret: pointer to an address where to store the created #idmef_data_t object.
 *
 * Create a new data object, children of #idmef_additional_data_t.
 * If @ptr already contain a #idmef_data_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_additional_data_new_data(idmef_additional_data_t *ptr, idmef_data_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->data ) {
                retval = idmef_data_new(&ptr->data);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->data;
        return 0;
}

/**
 * idmef_additional_data_copy:
 * @src: Source of the copy.
 * @dst: Where to copy the object.
 *
 * Copy a new #idmef_additional_data_t object from @src to @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_additional_data_copy(const idmef_additional_data_t *src, idmef_additional_data_t *dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));
        prelude_return_val_if_fail(dst, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = 0;

        if ( dst->meaning ) {
                prelude_string_destroy(dst->meaning);
                dst->meaning = NULL;
        }

        if ( src->meaning ) {
                ret = prelude_string_clone(src->meaning, &dst->meaning);
                if ( ret < 0 )
                        return ret;
        }

        dst->type = src->type;

        if ( src->data ) {
                ret = idmef_data_copy(src->data, dst->data);
                if ( ret < 0 )
                        return ret;
        }

        return 0;
}

/**
 * idmef_additional_data_clone:
 * @src: Object to be cloned.
 * @dst: Address where to store the pointer to the cloned object.
 *
 * Create a copy of @src, and store it in @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_additional_data_clone(idmef_additional_data_t *src, idmef_additional_data_t **dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = idmef_additional_data_new(dst);
        if ( ret < 0 )
                return ret;

        return idmef_additional_data_copy(src, *dst);
}

/**
 * idmef_additional_data_compare:
 * @obj1: Object to compare with @obj2.
 * @obj2: Object to compare with @obj1.
 *
 * Compare @obj1 with @obj2.
 *
 * Returns: 0 on match, a negative value on comparison failure.
 */
int idmef_additional_data_compare(const idmef_additional_data_t *obj1, const idmef_additional_data_t *obj2)
{
        int ret = 0;

        if ( obj1 == NULL && obj2 == NULL )
                return 0;

        else if ( obj1 == NULL || obj2 == NULL )
                return -1;

        ret = prelude_string_compare(obj1->meaning, obj2->meaning);
        if ( ret != 0 )
                return ret;

        if ( obj1->type != obj2->type )
                return -1;

        ret = idmef_data_compare(obj1->data, obj2->data);
        if ( ret != 0 )
                return ret;

        return ret;
}

/**
 * idmef_reference_new:
 * @ret: Pointer where to store the created #idmef_reference_t object.
 *
 * Create a new #idmef_reference_t object.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_reference_new(idmef_reference_t **ret)
{
        *ret = calloc(1, sizeof(**ret));
        if ( ! *ret )
                return prelude_error_from_errno(errno);

        (*ret)->_idmef_object_id = IDMEF_CLASS_ID_REFERENCE;

        prelude_list_init(&((prelude_linked_object_t *) (*ret))->_list);

        (*ret)->refcount = 1;

        {
                int retval = prelude_string_new(&(*ret)->name);

                if ( retval < 0 ) {
                        idmef_reference_destroy(*ret);
                        *ret = NULL;
                        return retval;
                }
        }

        {
                int retval = prelude_string_new(&(*ret)->url);

                if ( retval < 0 ) {
                        idmef_reference_destroy(*ret);
                        *ret = NULL;
                        return retval;
                }
        }

        return 0;

}

/**
 * idmef_reference_ref:
 * @reference: pointer to a #idmef_reference_t object.
 *
 * Increase @reference reference count, so that it can be referenced
 * multiple time.
 *
 * Returns: a pointer to @reference.
 */
idmef_reference_t *idmef_reference_ref(idmef_reference_t *reference)
{
        prelude_return_val_if_fail(reference, NULL);
        reference->refcount++;

        return reference;
}

int _idmef_reference_get_child(void *p, idmef_class_child_id_t child, void **childptr)
{
        idmef_reference_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));
        *childptr = NULL;

        switch ( child ) {

                case 0:
                       return idmef_value_new_enum_from_numeric((idmef_value_t **) childptr,
                                                                IDMEF_CLASS_ID_REFERENCE_ORIGIN, ptr->origin);

                case 1:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->name, TRUE);
                case 2:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->url, TRUE);
                case 3:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->meaning, TRUE);
                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_reference_new_child(void *p, idmef_class_child_id_t child, int n, void **ret)
{
        idmef_reference_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        return idmef_reference_new_origin(ptr, (idmef_reference_origin_t **) ret);

                case 1:
                        return idmef_reference_new_name(ptr, (prelude_string_t **) ret);

                case 2:
                        return idmef_reference_new_url(ptr, (prelude_string_t **) ret);

                case 3:
                        return idmef_reference_new_meaning(ptr, (prelude_string_t **) ret);

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_reference_destroy_child(void *p, idmef_class_child_id_t child, int n)
{
        idmef_reference_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        ptr->origin = 0;
                        return 0;

                case 1:
                        if ( ptr->name ) {
                                prelude_string_destroy(ptr->name);
                                ptr->name = NULL;
                        }

                        return 0;

                case 2:
                        if ( ptr->url ) {
                                prelude_string_destroy(ptr->url);
                                ptr->url = NULL;
                        }

                        return 0;

                case 3:
                        if ( ptr->meaning ) {
                                prelude_string_destroy(ptr->meaning);
                                ptr->meaning = NULL;
                        }

                        return 0;

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

static void idmef_reference_destroy_internal(idmef_reference_t *ptr)
{
        prelude_return_if_fail(ptr);

       if ( ! prelude_list_is_empty(&((prelude_linked_object_t *)ptr)->_list) )
               prelude_list_del_init(&((prelude_linked_object_t *)ptr)->_list);
    
        if ( ptr->name ) {
                prelude_string_destroy(ptr->name);
                ptr->name = NULL;
        }

        if ( ptr->url ) {
                prelude_string_destroy(ptr->url);
                ptr->url = NULL;
        }

        if ( ptr->meaning ) {
                prelude_string_destroy(ptr->meaning);
                ptr->meaning = NULL;
        }


        /* free() should be done by the caller */
}

/**
 * idmef_reference_destroy:
 * @ptr: pointer to a #idmef_reference_t object.
 *
 * Destroy @ptr and all of it's children.
 * The objects are only destroyed if their reference count reach zero.
 */

void idmef_reference_destroy(idmef_reference_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( --ptr->refcount )
                return;

        idmef_reference_destroy_internal(ptr);
        free(ptr);
}

/**
 * idmef_reference_get_origin:
 * @ptr: pointer to a #idmef_reference_t object.
 *
 * Get origin children of the #idmef_reference_t object.
 *
 * Returns: a pointer to a idmef_reference_origin_t object, or NULL if the children object is not set.
 */
idmef_reference_origin_t idmef_reference_get_origin(idmef_reference_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->origin;
}

/**
 * idmef_reference_set_origin:
 * @ptr: pointer to a #idmef_reference_t object.
 * @origin: pointer to a #idmef_reference_origin_t object.
 *
 * Set @origin object as a children of @ptr.
 * if @ptr already contain an @origin object, then it is destroyed,
 * and updated to point to the provided @origin object.
 */

void idmef_reference_set_origin(idmef_reference_t *ptr, idmef_reference_origin_t origin)
{
        prelude_return_if_fail(ptr);
        ptr->origin = origin;
}

/**
 * idmef_reference_new_origin:
 * @ptr: pointer to a #idmef_reference_t object.
 * @ret: pointer to an address where to store the created #idmef_reference_origin_t object.
 *
 * Create a new origin object, children of #idmef_reference_t.
 * If @ptr already contain a #idmef_reference_origin_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_reference_new_origin(idmef_reference_t *ptr, idmef_reference_origin_t **ret)
{
        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        *ret = &ptr->origin;
        return 0;
}

/**
 * idmef_reference_get_name:
 * @ptr: pointer to a #idmef_reference_t object.
 *
 * Get name children of the #idmef_reference_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_reference_get_name(idmef_reference_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->name;
}

/**
 * idmef_reference_set_name:
 * @ptr: pointer to a #idmef_reference_t object.
 * @name: pointer to a #prelude_string_t object.
 *
 * Set @name object as a children of @ptr.
 * if @ptr already contain an @name object, then it is destroyed,
 * and updated to point to the provided @name object.
 */

void idmef_reference_set_name(idmef_reference_t *ptr, prelude_string_t *name)
{
        prelude_return_if_fail(ptr);

        if ( ptr->name )
                prelude_string_destroy(ptr->name);

        ptr->name = name;
}

/**
 * idmef_reference_new_name:
 * @ptr: pointer to a #idmef_reference_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new name object, children of #idmef_reference_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_reference_new_name(idmef_reference_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->name ) {
                retval = prelude_string_new(&ptr->name);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->name;
        return 0;
}

/**
 * idmef_reference_get_url:
 * @ptr: pointer to a #idmef_reference_t object.
 *
 * Get url children of the #idmef_reference_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_reference_get_url(idmef_reference_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->url;
}

/**
 * idmef_reference_set_url:
 * @ptr: pointer to a #idmef_reference_t object.
 * @url: pointer to a #prelude_string_t object.
 *
 * Set @url object as a children of @ptr.
 * if @ptr already contain an @url object, then it is destroyed,
 * and updated to point to the provided @url object.
 */

void idmef_reference_set_url(idmef_reference_t *ptr, prelude_string_t *url)
{
        prelude_return_if_fail(ptr);

        if ( ptr->url )
                prelude_string_destroy(ptr->url);

        ptr->url = url;
}

/**
 * idmef_reference_new_url:
 * @ptr: pointer to a #idmef_reference_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new url object, children of #idmef_reference_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_reference_new_url(idmef_reference_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->url ) {
                retval = prelude_string_new(&ptr->url);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->url;
        return 0;
}

/**
 * idmef_reference_get_meaning:
 * @ptr: pointer to a #idmef_reference_t object.
 *
 * Get meaning children of the #idmef_reference_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_reference_get_meaning(idmef_reference_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->meaning;
}

/**
 * idmef_reference_set_meaning:
 * @ptr: pointer to a #idmef_reference_t object.
 * @meaning: pointer to a #prelude_string_t object.
 *
 * Set @meaning object as a children of @ptr.
 * if @ptr already contain an @meaning object, then it is destroyed,
 * and updated to point to the provided @meaning object.
 */

void idmef_reference_set_meaning(idmef_reference_t *ptr, prelude_string_t *meaning)
{
        prelude_return_if_fail(ptr);

        if ( ptr->meaning )
                prelude_string_destroy(ptr->meaning);

        ptr->meaning = meaning;
}

/**
 * idmef_reference_new_meaning:
 * @ptr: pointer to a #idmef_reference_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new meaning object, children of #idmef_reference_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_reference_new_meaning(idmef_reference_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->meaning ) {
                retval = prelude_string_new(&ptr->meaning);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->meaning;
        return 0;
}

/**
 * idmef_reference_copy:
 * @src: Source of the copy.
 * @dst: Where to copy the object.
 *
 * Copy a new #idmef_reference_t object from @src to @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_reference_copy(const idmef_reference_t *src, idmef_reference_t *dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));
        prelude_return_val_if_fail(dst, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = 0;

        dst->origin = src->origin;

        if ( src->name ) {
                ret = prelude_string_copy(src->name, dst->name);
                if ( ret < 0 )
                        return ret;
        }

        if ( src->url ) {
                ret = prelude_string_copy(src->url, dst->url);
                if ( ret < 0 )
                        return ret;
        }

        if ( dst->meaning ) {
                prelude_string_destroy(dst->meaning);
                dst->meaning = NULL;
        }

        if ( src->meaning ) {
                ret = prelude_string_clone(src->meaning, &dst->meaning);
                if ( ret < 0 )
                        return ret;
        }

        return 0;
}

/**
 * idmef_reference_clone:
 * @src: Object to be cloned.
 * @dst: Address where to store the pointer to the cloned object.
 *
 * Create a copy of @src, and store it in @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_reference_clone(idmef_reference_t *src, idmef_reference_t **dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = idmef_reference_new(dst);
        if ( ret < 0 )
                return ret;

        return idmef_reference_copy(src, *dst);
}

/**
 * idmef_reference_compare:
 * @obj1: Object to compare with @obj2.
 * @obj2: Object to compare with @obj1.
 *
 * Compare @obj1 with @obj2.
 *
 * Returns: 0 on match, a negative value on comparison failure.
 */
int idmef_reference_compare(const idmef_reference_t *obj1, const idmef_reference_t *obj2)
{
        int ret = 0;

        if ( obj1 == NULL && obj2 == NULL )
                return 0;

        else if ( obj1 == NULL || obj2 == NULL )
                return -1;

        if ( obj1->origin != obj2->origin )
                return -1;

        ret = prelude_string_compare(obj1->name, obj2->name);
        if ( ret != 0 )
                return ret;

        ret = prelude_string_compare(obj1->url, obj2->url);
        if ( ret != 0 )
                return ret;

        ret = prelude_string_compare(obj1->meaning, obj2->meaning);
        if ( ret != 0 )
                return ret;

        return ret;
}

/**
 * idmef_classification_new:
 * @ret: Pointer where to store the created #idmef_classification_t object.
 *
 * Create a new #idmef_classification_t object.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_classification_new(idmef_classification_t **ret)
{
        *ret = calloc(1, sizeof(**ret));
        if ( ! *ret )
                return prelude_error_from_errno(errno);

        (*ret)->_idmef_object_id = IDMEF_CLASS_ID_CLASSIFICATION;

        (*ret)->refcount = 1;

        prelude_list_init(&(*ret)->reference_list);


        {
                int retval = prelude_string_new(&(*ret)->text);

                if ( retval < 0 ) {
                        idmef_classification_destroy(*ret);
                        *ret = NULL;
                        return retval;
                }
        }

        return 0;

}

/**
 * idmef_classification_ref:
 * @classification: pointer to a #idmef_classification_t object.
 *
 * Increase @classification reference count, so that it can be referenced
 * multiple time.
 *
 * Returns: a pointer to @classification.
 */
idmef_classification_t *idmef_classification_ref(idmef_classification_t *classification)
{
        prelude_return_val_if_fail(classification, NULL);
        classification->refcount++;

        return classification;
}

int _idmef_classification_get_child(void *p, idmef_class_child_id_t child, void **childptr)
{
        idmef_classification_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));
        *childptr = NULL;

        switch ( child ) {

                case 0:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->ident, TRUE);
                case 1:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->text, TRUE);
                case 2:
                        *childptr = &ptr->reference_list;
                        return 0;

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_classification_new_child(void *p, idmef_class_child_id_t child, int n, void **ret)
{
        idmef_classification_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        return idmef_classification_new_ident(ptr, (prelude_string_t **) ret);

                case 1:
                        return idmef_classification_new_text(ptr, (prelude_string_t **) ret);

                case 2: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n == IDMEF_LIST_APPEND || n == IDMEF_LIST_PREPEND )
                               return idmef_classification_new_reference(ptr, (idmef_reference_t **) ret, n);

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->reference_list, tmp) {
                                       if ( i++ == n ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->reference_list, tmp) {
                                       if ( i++ == pos ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }

                        return idmef_classification_new_reference(ptr, (idmef_reference_t **) ret, n);
                }

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_classification_destroy_child(void *p, idmef_class_child_id_t child, int n)
{
        idmef_classification_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        if ( ptr->ident ) {
                                prelude_string_destroy(ptr->ident);
                                ptr->ident = NULL;
                        }

                        return 0;

                case 1:
                        if ( ptr->text ) {
                                prelude_string_destroy(ptr->text);
                                ptr->text = NULL;
                        }

                        return 0;

                case 2: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->reference_list, tmp) {
                                       if ( i++ == n ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               idmef_reference_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->reference_list, tmp) {
                                       if ( i++ == pos ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               idmef_reference_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }
                }

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

static void idmef_classification_destroy_internal(idmef_classification_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( ptr->ident ) {
                prelude_string_destroy(ptr->ident);
                ptr->ident = NULL;
        }

        if ( ptr->text ) {
                prelude_string_destroy(ptr->text);
                ptr->text = NULL;
        }

        {
                prelude_list_t *n, *tmp;
                idmef_reference_t *entry;

                prelude_list_for_each_safe(&ptr->reference_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        prelude_list_del_init(tmp);
                        idmef_reference_destroy(entry);
                }
        }


        /* free() should be done by the caller */
}

/**
 * idmef_classification_destroy:
 * @ptr: pointer to a #idmef_classification_t object.
 *
 * Destroy @ptr and all of it's children.
 * The objects are only destroyed if their reference count reach zero.
 */

void idmef_classification_destroy(idmef_classification_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( --ptr->refcount )
                return;

        idmef_classification_destroy_internal(ptr);
        free(ptr);
}

/**
 * idmef_classification_get_ident:
 * @ptr: pointer to a #idmef_classification_t object.
 *
 * Get ident children of the #idmef_classification_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_classification_get_ident(idmef_classification_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->ident;
}

/**
 * idmef_classification_set_ident:
 * @ptr: pointer to a #idmef_classification_t object.
 * @ident: pointer to a #prelude_string_t object.
 *
 * Set @ident object as a children of @ptr.
 * if @ptr already contain an @ident object, then it is destroyed,
 * and updated to point to the provided @ident object.
 */

void idmef_classification_set_ident(idmef_classification_t *ptr, prelude_string_t *ident)
{
        prelude_return_if_fail(ptr);

        if ( ptr->ident )
                prelude_string_destroy(ptr->ident);

        ptr->ident = ident;
}

/**
 * idmef_classification_new_ident:
 * @ptr: pointer to a #idmef_classification_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new ident object, children of #idmef_classification_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_classification_new_ident(idmef_classification_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->ident ) {
                retval = prelude_string_new(&ptr->ident);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->ident;
        return 0;
}

/**
 * idmef_classification_get_text:
 * @ptr: pointer to a #idmef_classification_t object.
 *
 * Get text children of the #idmef_classification_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_classification_get_text(idmef_classification_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->text;
}

/**
 * idmef_classification_set_text:
 * @ptr: pointer to a #idmef_classification_t object.
 * @text: pointer to a #prelude_string_t object.
 *
 * Set @text object as a children of @ptr.
 * if @ptr already contain an @text object, then it is destroyed,
 * and updated to point to the provided @text object.
 */

void idmef_classification_set_text(idmef_classification_t *ptr, prelude_string_t *text)
{
        prelude_return_if_fail(ptr);

        if ( ptr->text )
                prelude_string_destroy(ptr->text);

        ptr->text = text;
}

/**
 * idmef_classification_new_text:
 * @ptr: pointer to a #idmef_classification_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new text object, children of #idmef_classification_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_classification_new_text(idmef_classification_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->text ) {
                retval = prelude_string_new(&ptr->text);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->text;
        return 0;
}

/**
 * idmef_classification_get_next_reference:
 * @classification: pointer to a #idmef_classification_t object.
 * @reference_cur: pointer to a #idmef_reference_t object.
 *
 * Get the next #idmef_reference_t object listed in @ptr.
 * When iterating over the idmef_reference_t object listed in @ptr,
 * @object should be set to the latest returned #idmef_reference_t object.
 *
 * Returns: the next #idmef_reference_t in the list.
 */
idmef_reference_t *idmef_classification_get_next_reference(idmef_classification_t *classification, idmef_reference_t *reference_cur)
{
        prelude_list_t *tmp = (reference_cur) ? &((prelude_linked_object_t *) reference_cur)->_list : NULL;

        prelude_return_val_if_fail(classification, NULL);

        prelude_list_for_each_continue(&classification->reference_list, tmp)
                return prelude_linked_object_get_object(tmp);

        return NULL;
}


/**
 * idmef_classification_set_reference:
 * @ptr: pointer to a #idmef_classification_t object.
 * @object: pointer to a #idmef_reference_t object.
 * @pos: Position in the list.
 *
 * Add @object to position @pos of @ptr list of #idmef_reference_t object.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 */
void idmef_classification_set_reference(idmef_classification_t *ptr, idmef_reference_t *object, int pos)
{
        prelude_return_if_fail(ptr);
        prelude_return_if_fail(object);

        if ( ! prelude_list_is_empty(&((prelude_linked_object_t *) object)->_list) )
                prelude_list_del_init(&((prelude_linked_object_t *) object)->_list);

        list_insert(&ptr->reference_list, &((prelude_linked_object_t *) object)->_list, pos);
}


/**
 * idmef_classification_new_reference:
 * @ptr: pointer to a #idmef_classification_t object.
 * @ret: pointer to an address where to store the created #idmef_reference_t object.
 * @pos: position in the list.
 *
 * Create a new #idmef_reference_t children of @ptr, and add it to position @pos of
 * @ptr list of #idmef_reference_t object. The created #idmef_reference_t object is
 * stored in @ret.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_classification_new_reference(idmef_classification_t *ptr, idmef_reference_t **ret, int pos)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        retval = idmef_reference_new(ret);
        if ( retval < 0 )
                return retval;

        list_insert(&ptr->reference_list, &((prelude_linked_object_t *)(*ret))->_list, pos);

        return 0;
}


/**
 * idmef_classification_copy:
 * @src: Source of the copy.
 * @dst: Where to copy the object.
 *
 * Copy a new #idmef_classification_t object from @src to @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_classification_copy(const idmef_classification_t *src, idmef_classification_t *dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));
        prelude_return_val_if_fail(dst, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = 0;

        if ( dst->ident ) {
                prelude_string_destroy(dst->ident);
                dst->ident = NULL;
        }

        if ( src->ident ) {
                ret = prelude_string_clone(src->ident, &dst->ident);
                if ( ret < 0 )
                        return ret;
        }

        if ( src->text ) {
                ret = prelude_string_copy(src->text, dst->text);
                if ( ret < 0 )
                        return ret;
        }

        {
                prelude_list_t *n, *tmp;
                idmef_reference_t *entry, *new;

                prelude_list_for_each_safe(&dst->reference_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        idmef_reference_destroy(entry);
                }

                prelude_list_for_each_safe(&src->reference_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        idmef_reference_clone(entry, &new);
                        prelude_list_add_tail(&dst->reference_list, &((prelude_linked_object_t *) new)->_list);
                }
        }

        return 0;
}

/**
 * idmef_classification_clone:
 * @src: Object to be cloned.
 * @dst: Address where to store the pointer to the cloned object.
 *
 * Create a copy of @src, and store it in @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_classification_clone(idmef_classification_t *src, idmef_classification_t **dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = idmef_classification_new(dst);
        if ( ret < 0 )
                return ret;

        return idmef_classification_copy(src, *dst);
}

/**
 * idmef_classification_compare:
 * @obj1: Object to compare with @obj2.
 * @obj2: Object to compare with @obj1.
 *
 * Compare @obj1 with @obj2.
 *
 * Returns: 0 on match, a negative value on comparison failure.
 */
int idmef_classification_compare(const idmef_classification_t *obj1, const idmef_classification_t *obj2)
{
        int ret = 0;

        if ( obj1 == NULL && obj2 == NULL )
                return 0;

        else if ( obj1 == NULL || obj2 == NULL )
                return -1;

        ret = prelude_string_compare(obj1->ident, obj2->ident);
        if ( ret != 0 )
                return ret;

        ret = prelude_string_compare(obj1->text, obj2->text);
        if ( ret != 0 )
                return ret;

        {
                prelude_list_t *tmp1, *tmp2;
                idmef_reference_t *entry1, *entry2;

                tmp1 = tmp2 = NULL;
                do {
                        entry1 = entry2 = NULL;

                        prelude_list_for_each_continue(&obj1->reference_list, tmp1) {
                                entry1 = prelude_linked_object_get_object(tmp1);
                                break;
                        }

                        prelude_list_for_each_continue(&obj2->reference_list, tmp2) {
                                entry2 = prelude_linked_object_get_object(tmp2);
                                break;
                        }

                        ret = idmef_reference_compare(entry1, entry2);
                        if ( ret != 0 )
                                return ret;

                } while ( entry1 && entry2 );
        }

        return ret;
}

/**
 * idmef_user_id_new:
 * @ret: Pointer where to store the created #idmef_user_id_t object.
 *
 * Create a new #idmef_user_id_t object.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_user_id_new(idmef_user_id_t **ret)
{
        *ret = calloc(1, sizeof(**ret));
        if ( ! *ret )
                return prelude_error_from_errno(errno);

        (*ret)->_idmef_object_id = IDMEF_CLASS_ID_USER_ID;

        prelude_list_init(&((prelude_linked_object_t *) (*ret))->_list);

        (*ret)->refcount = 1;

        return 0;

}

/**
 * idmef_user_id_ref:
 * @user_id: pointer to a #idmef_user_id_t object.
 *
 * Increase @user_id reference count, so that it can be referenced
 * multiple time.
 *
 * Returns: a pointer to @user_id.
 */
idmef_user_id_t *idmef_user_id_ref(idmef_user_id_t *user_id)
{
        prelude_return_val_if_fail(user_id, NULL);
        user_id->refcount++;

        return user_id;
}

int _idmef_user_id_get_child(void *p, idmef_class_child_id_t child, void **childptr)
{
        idmef_user_id_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));
        *childptr = NULL;

        switch ( child ) {

                case 0:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->ident, TRUE);
                case 1:
                       return idmef_value_new_enum_from_numeric((idmef_value_t **) childptr,
                                                                IDMEF_CLASS_ID_USER_ID_TYPE, ptr->type);

                case 2:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->tty, TRUE);
                case 3:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->name, TRUE);
                case 4:
                       return (ptr->number_is_set) ? idmef_value_new_uint32((idmef_value_t **) childptr, ptr->number) : 0;

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_user_id_new_child(void *p, idmef_class_child_id_t child, int n, void **ret)
{
        idmef_user_id_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        return idmef_user_id_new_ident(ptr, (prelude_string_t **) ret);

                case 1:
                        return idmef_user_id_new_type(ptr, (idmef_user_id_type_t **) ret);

                case 2:
                        return idmef_user_id_new_tty(ptr, (prelude_string_t **) ret);

                case 3:
                        return idmef_user_id_new_name(ptr, (prelude_string_t **) ret);

                case 4:
                        return idmef_user_id_new_number(ptr, (uint32_t **) ret);

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_user_id_destroy_child(void *p, idmef_class_child_id_t child, int n)
{
        idmef_user_id_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        if ( ptr->ident ) {
                                prelude_string_destroy(ptr->ident);
                                ptr->ident = NULL;
                        }

                        return 0;

                case 1:
                        ptr->type = 0;
                        return 0;

                case 2:
                        if ( ptr->tty ) {
                                prelude_string_destroy(ptr->tty);
                                ptr->tty = NULL;
                        }

                        return 0;

                case 3:
                        if ( ptr->name ) {
                                prelude_string_destroy(ptr->name);
                                ptr->name = NULL;
                        }

                        return 0;

                case 4:
                        ptr->number_is_set = 0;
                        return 0;

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

static void idmef_user_id_destroy_internal(idmef_user_id_t *ptr)
{
        prelude_return_if_fail(ptr);

       if ( ! prelude_list_is_empty(&((prelude_linked_object_t *)ptr)->_list) )
               prelude_list_del_init(&((prelude_linked_object_t *)ptr)->_list);
    
        if ( ptr->ident ) {
                prelude_string_destroy(ptr->ident);
                ptr->ident = NULL;
        }

        if ( ptr->tty ) {
                prelude_string_destroy(ptr->tty);
                ptr->tty = NULL;
        }

        if ( ptr->name ) {
                prelude_string_destroy(ptr->name);
                ptr->name = NULL;
        }


        /* free() should be done by the caller */
}

/**
 * idmef_user_id_destroy:
 * @ptr: pointer to a #idmef_user_id_t object.
 *
 * Destroy @ptr and all of it's children.
 * The objects are only destroyed if their reference count reach zero.
 */

void idmef_user_id_destroy(idmef_user_id_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( --ptr->refcount )
                return;

        idmef_user_id_destroy_internal(ptr);
        free(ptr);
}

/**
 * idmef_user_id_get_ident:
 * @ptr: pointer to a #idmef_user_id_t object.
 *
 * Get ident children of the #idmef_user_id_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_user_id_get_ident(idmef_user_id_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->ident;
}

/**
 * idmef_user_id_set_ident:
 * @ptr: pointer to a #idmef_user_id_t object.
 * @ident: pointer to a #prelude_string_t object.
 *
 * Set @ident object as a children of @ptr.
 * if @ptr already contain an @ident object, then it is destroyed,
 * and updated to point to the provided @ident object.
 */

void idmef_user_id_set_ident(idmef_user_id_t *ptr, prelude_string_t *ident)
{
        prelude_return_if_fail(ptr);

        if ( ptr->ident )
                prelude_string_destroy(ptr->ident);

        ptr->ident = ident;
}

/**
 * idmef_user_id_new_ident:
 * @ptr: pointer to a #idmef_user_id_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new ident object, children of #idmef_user_id_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_user_id_new_ident(idmef_user_id_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->ident ) {
                retval = prelude_string_new(&ptr->ident);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->ident;
        return 0;
}

/**
 * idmef_user_id_get_type:
 * @ptr: pointer to a #idmef_user_id_t object.
 *
 * Get type children of the #idmef_user_id_t object.
 *
 * Returns: a pointer to a idmef_user_id_type_t object, or NULL if the children object is not set.
 */
idmef_user_id_type_t idmef_user_id_get_type(idmef_user_id_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->type;
}

/**
 * idmef_user_id_set_type:
 * @ptr: pointer to a #idmef_user_id_t object.
 * @type: pointer to a #idmef_user_id_type_t object.
 *
 * Set @type object as a children of @ptr.
 * if @ptr already contain an @type object, then it is destroyed,
 * and updated to point to the provided @type object.
 */

void idmef_user_id_set_type(idmef_user_id_t *ptr, idmef_user_id_type_t type)
{
        prelude_return_if_fail(ptr);
        ptr->type = type;
}

/**
 * idmef_user_id_new_type:
 * @ptr: pointer to a #idmef_user_id_t object.
 * @ret: pointer to an address where to store the created #idmef_user_id_type_t object.
 *
 * Create a new type object, children of #idmef_user_id_t.
 * If @ptr already contain a #idmef_user_id_type_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_user_id_new_type(idmef_user_id_t *ptr, idmef_user_id_type_t **ret)
{
        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        *ret = &ptr->type;
        return 0;
}

/**
 * idmef_user_id_get_tty:
 * @ptr: pointer to a #idmef_user_id_t object.
 *
 * Get tty children of the #idmef_user_id_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_user_id_get_tty(idmef_user_id_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->tty;
}

/**
 * idmef_user_id_set_tty:
 * @ptr: pointer to a #idmef_user_id_t object.
 * @tty: pointer to a #prelude_string_t object.
 *
 * Set @tty object as a children of @ptr.
 * if @ptr already contain an @tty object, then it is destroyed,
 * and updated to point to the provided @tty object.
 */

void idmef_user_id_set_tty(idmef_user_id_t *ptr, prelude_string_t *tty)
{
        prelude_return_if_fail(ptr);

        if ( ptr->tty )
                prelude_string_destroy(ptr->tty);

        ptr->tty = tty;
}

/**
 * idmef_user_id_new_tty:
 * @ptr: pointer to a #idmef_user_id_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new tty object, children of #idmef_user_id_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_user_id_new_tty(idmef_user_id_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->tty ) {
                retval = prelude_string_new(&ptr->tty);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->tty;
        return 0;
}

/**
 * idmef_user_id_get_name:
 * @ptr: pointer to a #idmef_user_id_t object.
 *
 * Get name children of the #idmef_user_id_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_user_id_get_name(idmef_user_id_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->name;
}

/**
 * idmef_user_id_set_name:
 * @ptr: pointer to a #idmef_user_id_t object.
 * @name: pointer to a #prelude_string_t object.
 *
 * Set @name object as a children of @ptr.
 * if @ptr already contain an @name object, then it is destroyed,
 * and updated to point to the provided @name object.
 */

void idmef_user_id_set_name(idmef_user_id_t *ptr, prelude_string_t *name)
{
        prelude_return_if_fail(ptr);

        if ( ptr->name )
                prelude_string_destroy(ptr->name);

        ptr->name = name;
}

/**
 * idmef_user_id_new_name:
 * @ptr: pointer to a #idmef_user_id_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new name object, children of #idmef_user_id_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_user_id_new_name(idmef_user_id_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->name ) {
                retval = prelude_string_new(&ptr->name);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->name;
        return 0;
}

/**
 * idmef_user_id_get_number:
 * @ptr: pointer to a #idmef_user_id_t object.
 *
 * Get number children of the #idmef_user_id_t object.
 *
 * Returns: a pointer to a uint32_t object, or NULL if the children object is not set.
 */
uint32_t *idmef_user_id_get_number(idmef_user_id_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->number_is_set ? &ptr->number : NULL;
}

/**
 * idmef_user_id_set_number:
 * @ptr: pointer to a #idmef_user_id_t object.
 * @number: pointer to a #uint32_t object.
 *
 * Set @number object as a children of @ptr.
 * if @ptr already contain an @number object, then it is destroyed,
 * and updated to point to the provided @number object.
 */

void idmef_user_id_set_number(idmef_user_id_t *ptr, uint32_t number)
{
        prelude_return_if_fail(ptr);
        ptr->number = number;
        ptr->number_is_set = 1;
}


void idmef_user_id_unset_number(idmef_user_id_t *ptr)
{
        prelude_return_if_fail(ptr);
        ptr->number_is_set = 0;
}


/**
 * idmef_user_id_new_number:
 * @ptr: pointer to a #idmef_user_id_t object.
 * @ret: pointer to an address where to store the created #uint32_t object.
 *
 * Create a new number object, children of #idmef_user_id_t.
 * If @ptr already contain a #uint32_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_user_id_new_number(idmef_user_id_t *ptr, uint32_t **ret)
{
        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));
        ptr->number_is_set = 1;

        *ret = &ptr->number;
        return 0;
}

/**
 * idmef_user_id_copy:
 * @src: Source of the copy.
 * @dst: Where to copy the object.
 *
 * Copy a new #idmef_user_id_t object from @src to @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_user_id_copy(const idmef_user_id_t *src, idmef_user_id_t *dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));
        prelude_return_val_if_fail(dst, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = 0;

        if ( dst->ident ) {
                prelude_string_destroy(dst->ident);
                dst->ident = NULL;
        }

        if ( src->ident ) {
                ret = prelude_string_clone(src->ident, &dst->ident);
                if ( ret < 0 )
                        return ret;
        }

        dst->type = src->type;

        if ( dst->tty ) {
                prelude_string_destroy(dst->tty);
                dst->tty = NULL;
        }

        if ( src->tty ) {
                ret = prelude_string_clone(src->tty, &dst->tty);
                if ( ret < 0 )
                        return ret;
        }

        if ( dst->name ) {
                prelude_string_destroy(dst->name);
                dst->name = NULL;
        }

        if ( src->name ) {
                ret = prelude_string_clone(src->name, &dst->name);
                if ( ret < 0 )
                        return ret;
        }

        dst->number_is_set = src->number_is_set;

        dst->number = src->number;

        return 0;
}

/**
 * idmef_user_id_clone:
 * @src: Object to be cloned.
 * @dst: Address where to store the pointer to the cloned object.
 *
 * Create a copy of @src, and store it in @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_user_id_clone(idmef_user_id_t *src, idmef_user_id_t **dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = idmef_user_id_new(dst);
        if ( ret < 0 )
                return ret;

        return idmef_user_id_copy(src, *dst);
}

/**
 * idmef_user_id_compare:
 * @obj1: Object to compare with @obj2.
 * @obj2: Object to compare with @obj1.
 *
 * Compare @obj1 with @obj2.
 *
 * Returns: 0 on match, a negative value on comparison failure.
 */
int idmef_user_id_compare(const idmef_user_id_t *obj1, const idmef_user_id_t *obj2)
{
        int ret = 0;

        if ( obj1 == NULL && obj2 == NULL )
                return 0;

        else if ( obj1 == NULL || obj2 == NULL )
                return -1;

        ret = prelude_string_compare(obj1->ident, obj2->ident);
        if ( ret != 0 )
                return ret;

        if ( obj1->type != obj2->type )
                return -1;

        ret = prelude_string_compare(obj1->tty, obj2->tty);
        if ( ret != 0 )
                return ret;

        ret = prelude_string_compare(obj1->name, obj2->name);
        if ( ret != 0 )
                return ret;

        if ( obj1->number_is_set != obj2->number_is_set )
                return -1;

        if ( obj1->number_is_set && obj1->number != obj2->number )
                return -1;

        return ret;
}

/**
 * idmef_user_new:
 * @ret: Pointer where to store the created #idmef_user_t object.
 *
 * Create a new #idmef_user_t object.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_user_new(idmef_user_t **ret)
{
        *ret = calloc(1, sizeof(**ret));
        if ( ! *ret )
                return prelude_error_from_errno(errno);

        (*ret)->_idmef_object_id = IDMEF_CLASS_ID_USER;

        (*ret)->refcount = 1;

        prelude_list_init(&(*ret)->user_id_list);


        return 0;

}

/**
 * idmef_user_ref:
 * @user: pointer to a #idmef_user_t object.
 *
 * Increase @user reference count, so that it can be referenced
 * multiple time.
 *
 * Returns: a pointer to @user.
 */
idmef_user_t *idmef_user_ref(idmef_user_t *user)
{
        prelude_return_val_if_fail(user, NULL);
        user->refcount++;

        return user;
}

int _idmef_user_get_child(void *p, idmef_class_child_id_t child, void **childptr)
{
        idmef_user_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));
        *childptr = NULL;

        switch ( child ) {

                case 0:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->ident, TRUE);
                case 1:
                       return idmef_value_new_enum_from_numeric((idmef_value_t **) childptr,
                                                                IDMEF_CLASS_ID_USER_CATEGORY, ptr->category);

                case 2:
                        *childptr = &ptr->user_id_list;
                        return 0;

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_user_new_child(void *p, idmef_class_child_id_t child, int n, void **ret)
{
        idmef_user_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        return idmef_user_new_ident(ptr, (prelude_string_t **) ret);

                case 1:
                        return idmef_user_new_category(ptr, (idmef_user_category_t **) ret);

                case 2: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n == IDMEF_LIST_APPEND || n == IDMEF_LIST_PREPEND )
                               return idmef_user_new_user_id(ptr, (idmef_user_id_t **) ret, n);

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->user_id_list, tmp) {
                                       if ( i++ == n ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->user_id_list, tmp) {
                                       if ( i++ == pos ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }

                        return idmef_user_new_user_id(ptr, (idmef_user_id_t **) ret, n);
                }

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_user_destroy_child(void *p, idmef_class_child_id_t child, int n)
{
        idmef_user_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        if ( ptr->ident ) {
                                prelude_string_destroy(ptr->ident);
                                ptr->ident = NULL;
                        }

                        return 0;

                case 1:
                        ptr->category = 0;
                        return 0;

                case 2: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->user_id_list, tmp) {
                                       if ( i++ == n ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               idmef_user_id_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->user_id_list, tmp) {
                                       if ( i++ == pos ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               idmef_user_id_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }
                }

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

static void idmef_user_destroy_internal(idmef_user_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( ptr->ident ) {
                prelude_string_destroy(ptr->ident);
                ptr->ident = NULL;
        }

        {
                prelude_list_t *n, *tmp;
                idmef_user_id_t *entry;

                prelude_list_for_each_safe(&ptr->user_id_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        prelude_list_del_init(tmp);
                        idmef_user_id_destroy(entry);
                }
        }


        /* free() should be done by the caller */
}

/**
 * idmef_user_destroy:
 * @ptr: pointer to a #idmef_user_t object.
 *
 * Destroy @ptr and all of it's children.
 * The objects are only destroyed if their reference count reach zero.
 */

void idmef_user_destroy(idmef_user_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( --ptr->refcount )
                return;

        idmef_user_destroy_internal(ptr);
        free(ptr);
}

/**
 * idmef_user_get_ident:
 * @ptr: pointer to a #idmef_user_t object.
 *
 * Get ident children of the #idmef_user_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_user_get_ident(idmef_user_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->ident;
}

/**
 * idmef_user_set_ident:
 * @ptr: pointer to a #idmef_user_t object.
 * @ident: pointer to a #prelude_string_t object.
 *
 * Set @ident object as a children of @ptr.
 * if @ptr already contain an @ident object, then it is destroyed,
 * and updated to point to the provided @ident object.
 */

void idmef_user_set_ident(idmef_user_t *ptr, prelude_string_t *ident)
{
        prelude_return_if_fail(ptr);

        if ( ptr->ident )
                prelude_string_destroy(ptr->ident);

        ptr->ident = ident;
}

/**
 * idmef_user_new_ident:
 * @ptr: pointer to a #idmef_user_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new ident object, children of #idmef_user_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_user_new_ident(idmef_user_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->ident ) {
                retval = prelude_string_new(&ptr->ident);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->ident;
        return 0;
}

/**
 * idmef_user_get_category:
 * @ptr: pointer to a #idmef_user_t object.
 *
 * Get category children of the #idmef_user_t object.
 *
 * Returns: a pointer to a idmef_user_category_t object, or NULL if the children object is not set.
 */
idmef_user_category_t idmef_user_get_category(idmef_user_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->category;
}

/**
 * idmef_user_set_category:
 * @ptr: pointer to a #idmef_user_t object.
 * @category: pointer to a #idmef_user_category_t object.
 *
 * Set @category object as a children of @ptr.
 * if @ptr already contain an @category object, then it is destroyed,
 * and updated to point to the provided @category object.
 */

void idmef_user_set_category(idmef_user_t *ptr, idmef_user_category_t category)
{
        prelude_return_if_fail(ptr);
        ptr->category = category;
}

/**
 * idmef_user_new_category:
 * @ptr: pointer to a #idmef_user_t object.
 * @ret: pointer to an address where to store the created #idmef_user_category_t object.
 *
 * Create a new category object, children of #idmef_user_t.
 * If @ptr already contain a #idmef_user_category_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_user_new_category(idmef_user_t *ptr, idmef_user_category_t **ret)
{
        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        *ret = &ptr->category;
        return 0;
}

/**
 * idmef_user_get_next_user_id:
 * @user: pointer to a #idmef_user_t object.
 * @user_id_cur: pointer to a #idmef_user_id_t object.
 *
 * Get the next #idmef_user_id_t object listed in @ptr.
 * When iterating over the idmef_user_id_t object listed in @ptr,
 * @object should be set to the latest returned #idmef_user_id_t object.
 *
 * Returns: the next #idmef_user_id_t in the list.
 */
idmef_user_id_t *idmef_user_get_next_user_id(idmef_user_t *user, idmef_user_id_t *user_id_cur)
{
        prelude_list_t *tmp = (user_id_cur) ? &((prelude_linked_object_t *) user_id_cur)->_list : NULL;

        prelude_return_val_if_fail(user, NULL);

        prelude_list_for_each_continue(&user->user_id_list, tmp)
                return prelude_linked_object_get_object(tmp);

        return NULL;
}


/**
 * idmef_user_set_user_id:
 * @ptr: pointer to a #idmef_user_t object.
 * @object: pointer to a #idmef_user_id_t object.
 * @pos: Position in the list.
 *
 * Add @object to position @pos of @ptr list of #idmef_user_id_t object.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 */
void idmef_user_set_user_id(idmef_user_t *ptr, idmef_user_id_t *object, int pos)
{
        prelude_return_if_fail(ptr);
        prelude_return_if_fail(object);

        if ( ! prelude_list_is_empty(&((prelude_linked_object_t *) object)->_list) )
                prelude_list_del_init(&((prelude_linked_object_t *) object)->_list);

        list_insert(&ptr->user_id_list, &((prelude_linked_object_t *) object)->_list, pos);
}


/**
 * idmef_user_new_user_id:
 * @ptr: pointer to a #idmef_user_t object.
 * @ret: pointer to an address where to store the created #idmef_user_id_t object.
 * @pos: position in the list.
 *
 * Create a new #idmef_user_id_t children of @ptr, and add it to position @pos of
 * @ptr list of #idmef_user_id_t object. The created #idmef_user_id_t object is
 * stored in @ret.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_user_new_user_id(idmef_user_t *ptr, idmef_user_id_t **ret, int pos)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        retval = idmef_user_id_new(ret);
        if ( retval < 0 )
                return retval;

        list_insert(&ptr->user_id_list, &((prelude_linked_object_t *)(*ret))->_list, pos);

        return 0;
}


/**
 * idmef_user_copy:
 * @src: Source of the copy.
 * @dst: Where to copy the object.
 *
 * Copy a new #idmef_user_t object from @src to @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_user_copy(const idmef_user_t *src, idmef_user_t *dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));
        prelude_return_val_if_fail(dst, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = 0;

        if ( dst->ident ) {
                prelude_string_destroy(dst->ident);
                dst->ident = NULL;
        }

        if ( src->ident ) {
                ret = prelude_string_clone(src->ident, &dst->ident);
                if ( ret < 0 )
                        return ret;
        }

        dst->category = src->category;

        {
                prelude_list_t *n, *tmp;
                idmef_user_id_t *entry, *new;

                prelude_list_for_each_safe(&dst->user_id_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        idmef_user_id_destroy(entry);
                }

                prelude_list_for_each_safe(&src->user_id_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        idmef_user_id_clone(entry, &new);
                        prelude_list_add_tail(&dst->user_id_list, &((prelude_linked_object_t *) new)->_list);
                }
        }

        return 0;
}

/**
 * idmef_user_clone:
 * @src: Object to be cloned.
 * @dst: Address where to store the pointer to the cloned object.
 *
 * Create a copy of @src, and store it in @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_user_clone(idmef_user_t *src, idmef_user_t **dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = idmef_user_new(dst);
        if ( ret < 0 )
                return ret;

        return idmef_user_copy(src, *dst);
}

/**
 * idmef_user_compare:
 * @obj1: Object to compare with @obj2.
 * @obj2: Object to compare with @obj1.
 *
 * Compare @obj1 with @obj2.
 *
 * Returns: 0 on match, a negative value on comparison failure.
 */
int idmef_user_compare(const idmef_user_t *obj1, const idmef_user_t *obj2)
{
        int ret = 0;

        if ( obj1 == NULL && obj2 == NULL )
                return 0;

        else if ( obj1 == NULL || obj2 == NULL )
                return -1;

        ret = prelude_string_compare(obj1->ident, obj2->ident);
        if ( ret != 0 )
                return ret;

        if ( obj1->category != obj2->category )
                return -1;

        {
                prelude_list_t *tmp1, *tmp2;
                idmef_user_id_t *entry1, *entry2;

                tmp1 = tmp2 = NULL;
                do {
                        entry1 = entry2 = NULL;

                        prelude_list_for_each_continue(&obj1->user_id_list, tmp1) {
                                entry1 = prelude_linked_object_get_object(tmp1);
                                break;
                        }

                        prelude_list_for_each_continue(&obj2->user_id_list, tmp2) {
                                entry2 = prelude_linked_object_get_object(tmp2);
                                break;
                        }

                        ret = idmef_user_id_compare(entry1, entry2);
                        if ( ret != 0 )
                                return ret;

                } while ( entry1 && entry2 );
        }

        return ret;
}

/**
 * idmef_address_new:
 * @ret: Pointer where to store the created #idmef_address_t object.
 *
 * Create a new #idmef_address_t object.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_address_new(idmef_address_t **ret)
{
        *ret = calloc(1, sizeof(**ret));
        if ( ! *ret )
                return prelude_error_from_errno(errno);

        (*ret)->_idmef_object_id = IDMEF_CLASS_ID_ADDRESS;

        prelude_list_init(&((prelude_linked_object_t *) (*ret))->_list);

        (*ret)->refcount = 1;

        {
                int retval = prelude_string_new(&(*ret)->address);

                if ( retval < 0 ) {
                        idmef_address_destroy(*ret);
                        *ret = NULL;
                        return retval;
                }
        }

        return 0;

}

/**
 * idmef_address_ref:
 * @address: pointer to a #idmef_address_t object.
 *
 * Increase @address reference count, so that it can be referenced
 * multiple time.
 *
 * Returns: a pointer to @address.
 */
idmef_address_t *idmef_address_ref(idmef_address_t *address)
{
        prelude_return_val_if_fail(address, NULL);
        address->refcount++;

        return address;
}

int _idmef_address_get_child(void *p, idmef_class_child_id_t child, void **childptr)
{
        idmef_address_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));
        *childptr = NULL;

        switch ( child ) {

                case 0:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->ident, TRUE);
                case 1:
                       return idmef_value_new_enum_from_numeric((idmef_value_t **) childptr,
                                                                IDMEF_CLASS_ID_ADDRESS_CATEGORY, ptr->category);

                case 2:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->vlan_name, TRUE);
                case 3:
                       return (ptr->vlan_num_is_set) ? idmef_value_new_int32((idmef_value_t **) childptr, ptr->vlan_num) : 0;

                case 4:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->address, TRUE);
                case 5:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->netmask, TRUE);
                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_address_new_child(void *p, idmef_class_child_id_t child, int n, void **ret)
{
        idmef_address_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        return idmef_address_new_ident(ptr, (prelude_string_t **) ret);

                case 1:
                        return idmef_address_new_category(ptr, (idmef_address_category_t **) ret);

                case 2:
                        return idmef_address_new_vlan_name(ptr, (prelude_string_t **) ret);

                case 3:
                        return idmef_address_new_vlan_num(ptr, (int32_t **) ret);

                case 4:
                        return idmef_address_new_address(ptr, (prelude_string_t **) ret);

                case 5:
                        return idmef_address_new_netmask(ptr, (prelude_string_t **) ret);

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_address_destroy_child(void *p, idmef_class_child_id_t child, int n)
{
        idmef_address_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        if ( ptr->ident ) {
                                prelude_string_destroy(ptr->ident);
                                ptr->ident = NULL;
                        }

                        return 0;

                case 1:
                        ptr->category = 0;
                        return 0;

                case 2:
                        if ( ptr->vlan_name ) {
                                prelude_string_destroy(ptr->vlan_name);
                                ptr->vlan_name = NULL;
                        }

                        return 0;

                case 3:
                        ptr->vlan_num_is_set = 0;
                        return 0;

                case 4:
                        if ( ptr->address ) {
                                prelude_string_destroy(ptr->address);
                                ptr->address = NULL;
                        }

                        return 0;

                case 5:
                        if ( ptr->netmask ) {
                                prelude_string_destroy(ptr->netmask);
                                ptr->netmask = NULL;
                        }

                        return 0;

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

static void idmef_address_destroy_internal(idmef_address_t *ptr)
{
        prelude_return_if_fail(ptr);

       if ( ! prelude_list_is_empty(&((prelude_linked_object_t *)ptr)->_list) )
               prelude_list_del_init(&((prelude_linked_object_t *)ptr)->_list);
    
        if ( ptr->ident ) {
                prelude_string_destroy(ptr->ident);
                ptr->ident = NULL;
        }

        if ( ptr->vlan_name ) {
                prelude_string_destroy(ptr->vlan_name);
                ptr->vlan_name = NULL;
        }

        if ( ptr->address ) {
                prelude_string_destroy(ptr->address);
                ptr->address = NULL;
        }

        if ( ptr->netmask ) {
                prelude_string_destroy(ptr->netmask);
                ptr->netmask = NULL;
        }


        /* free() should be done by the caller */
}

/**
 * idmef_address_destroy:
 * @ptr: pointer to a #idmef_address_t object.
 *
 * Destroy @ptr and all of it's children.
 * The objects are only destroyed if their reference count reach zero.
 */

void idmef_address_destroy(idmef_address_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( --ptr->refcount )
                return;

        idmef_address_destroy_internal(ptr);
        free(ptr);
}

/**
 * idmef_address_get_ident:
 * @ptr: pointer to a #idmef_address_t object.
 *
 * Get ident children of the #idmef_address_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_address_get_ident(idmef_address_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->ident;
}

/**
 * idmef_address_set_ident:
 * @ptr: pointer to a #idmef_address_t object.
 * @ident: pointer to a #prelude_string_t object.
 *
 * Set @ident object as a children of @ptr.
 * if @ptr already contain an @ident object, then it is destroyed,
 * and updated to point to the provided @ident object.
 */

void idmef_address_set_ident(idmef_address_t *ptr, prelude_string_t *ident)
{
        prelude_return_if_fail(ptr);

        if ( ptr->ident )
                prelude_string_destroy(ptr->ident);

        ptr->ident = ident;
}

/**
 * idmef_address_new_ident:
 * @ptr: pointer to a #idmef_address_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new ident object, children of #idmef_address_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_address_new_ident(idmef_address_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->ident ) {
                retval = prelude_string_new(&ptr->ident);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->ident;
        return 0;
}

/**
 * idmef_address_get_category:
 * @ptr: pointer to a #idmef_address_t object.
 *
 * Get category children of the #idmef_address_t object.
 *
 * Returns: a pointer to a idmef_address_category_t object, or NULL if the children object is not set.
 */
idmef_address_category_t idmef_address_get_category(idmef_address_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->category;
}

/**
 * idmef_address_set_category:
 * @ptr: pointer to a #idmef_address_t object.
 * @category: pointer to a #idmef_address_category_t object.
 *
 * Set @category object as a children of @ptr.
 * if @ptr already contain an @category object, then it is destroyed,
 * and updated to point to the provided @category object.
 */

void idmef_address_set_category(idmef_address_t *ptr, idmef_address_category_t category)
{
        prelude_return_if_fail(ptr);
        ptr->category = category;
}

/**
 * idmef_address_new_category:
 * @ptr: pointer to a #idmef_address_t object.
 * @ret: pointer to an address where to store the created #idmef_address_category_t object.
 *
 * Create a new category object, children of #idmef_address_t.
 * If @ptr already contain a #idmef_address_category_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_address_new_category(idmef_address_t *ptr, idmef_address_category_t **ret)
{
        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        *ret = &ptr->category;
        return 0;
}

/**
 * idmef_address_get_vlan_name:
 * @ptr: pointer to a #idmef_address_t object.
 *
 * Get vlan_name children of the #idmef_address_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_address_get_vlan_name(idmef_address_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->vlan_name;
}

/**
 * idmef_address_set_vlan_name:
 * @ptr: pointer to a #idmef_address_t object.
 * @vlan_name: pointer to a #prelude_string_t object.
 *
 * Set @vlan_name object as a children of @ptr.
 * if @ptr already contain an @vlan_name object, then it is destroyed,
 * and updated to point to the provided @vlan_name object.
 */

void idmef_address_set_vlan_name(idmef_address_t *ptr, prelude_string_t *vlan_name)
{
        prelude_return_if_fail(ptr);

        if ( ptr->vlan_name )
                prelude_string_destroy(ptr->vlan_name);

        ptr->vlan_name = vlan_name;
}

/**
 * idmef_address_new_vlan_name:
 * @ptr: pointer to a #idmef_address_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new vlan_name object, children of #idmef_address_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_address_new_vlan_name(idmef_address_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->vlan_name ) {
                retval = prelude_string_new(&ptr->vlan_name);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->vlan_name;
        return 0;
}

/**
 * idmef_address_get_vlan_num:
 * @ptr: pointer to a #idmef_address_t object.
 *
 * Get vlan_num children of the #idmef_address_t object.
 *
 * Returns: a pointer to a int32_t object, or NULL if the children object is not set.
 */
int32_t *idmef_address_get_vlan_num(idmef_address_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->vlan_num_is_set ? &ptr->vlan_num : NULL;
}

/**
 * idmef_address_set_vlan_num:
 * @ptr: pointer to a #idmef_address_t object.
 * @vlan_num: pointer to a #int32_t object.
 *
 * Set @vlan_num object as a children of @ptr.
 * if @ptr already contain an @vlan_num object, then it is destroyed,
 * and updated to point to the provided @vlan_num object.
 */

void idmef_address_set_vlan_num(idmef_address_t *ptr, int32_t vlan_num)
{
        prelude_return_if_fail(ptr);
        ptr->vlan_num = vlan_num;
        ptr->vlan_num_is_set = 1;
}


void idmef_address_unset_vlan_num(idmef_address_t *ptr)
{
        prelude_return_if_fail(ptr);
        ptr->vlan_num_is_set = 0;
}


/**
 * idmef_address_new_vlan_num:
 * @ptr: pointer to a #idmef_address_t object.
 * @ret: pointer to an address where to store the created #int32_t object.
 *
 * Create a new vlan_num object, children of #idmef_address_t.
 * If @ptr already contain a #int32_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_address_new_vlan_num(idmef_address_t *ptr, int32_t **ret)
{
        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));
        ptr->vlan_num_is_set = 1;

        *ret = &ptr->vlan_num;
        return 0;
}

/**
 * idmef_address_get_address:
 * @ptr: pointer to a #idmef_address_t object.
 *
 * Get address children of the #idmef_address_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_address_get_address(idmef_address_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->address;
}

/**
 * idmef_address_set_address:
 * @ptr: pointer to a #idmef_address_t object.
 * @address: pointer to a #prelude_string_t object.
 *
 * Set @address object as a children of @ptr.
 * if @ptr already contain an @address object, then it is destroyed,
 * and updated to point to the provided @address object.
 */

void idmef_address_set_address(idmef_address_t *ptr, prelude_string_t *address)
{
        prelude_return_if_fail(ptr);

        if ( ptr->address )
                prelude_string_destroy(ptr->address);

        ptr->address = address;
}

/**
 * idmef_address_new_address:
 * @ptr: pointer to a #idmef_address_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new address object, children of #idmef_address_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_address_new_address(idmef_address_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->address ) {
                retval = prelude_string_new(&ptr->address);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->address;
        return 0;
}

/**
 * idmef_address_get_netmask:
 * @ptr: pointer to a #idmef_address_t object.
 *
 * Get netmask children of the #idmef_address_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_address_get_netmask(idmef_address_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->netmask;
}

/**
 * idmef_address_set_netmask:
 * @ptr: pointer to a #idmef_address_t object.
 * @netmask: pointer to a #prelude_string_t object.
 *
 * Set @netmask object as a children of @ptr.
 * if @ptr already contain an @netmask object, then it is destroyed,
 * and updated to point to the provided @netmask object.
 */

void idmef_address_set_netmask(idmef_address_t *ptr, prelude_string_t *netmask)
{
        prelude_return_if_fail(ptr);

        if ( ptr->netmask )
                prelude_string_destroy(ptr->netmask);

        ptr->netmask = netmask;
}

/**
 * idmef_address_new_netmask:
 * @ptr: pointer to a #idmef_address_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new netmask object, children of #idmef_address_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_address_new_netmask(idmef_address_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->netmask ) {
                retval = prelude_string_new(&ptr->netmask);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->netmask;
        return 0;
}

/**
 * idmef_address_copy:
 * @src: Source of the copy.
 * @dst: Where to copy the object.
 *
 * Copy a new #idmef_address_t object from @src to @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_address_copy(const idmef_address_t *src, idmef_address_t *dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));
        prelude_return_val_if_fail(dst, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = 0;

        if ( dst->ident ) {
                prelude_string_destroy(dst->ident);
                dst->ident = NULL;
        }

        if ( src->ident ) {
                ret = prelude_string_clone(src->ident, &dst->ident);
                if ( ret < 0 )
                        return ret;
        }

        dst->category = src->category;

        if ( dst->vlan_name ) {
                prelude_string_destroy(dst->vlan_name);
                dst->vlan_name = NULL;
        }

        if ( src->vlan_name ) {
                ret = prelude_string_clone(src->vlan_name, &dst->vlan_name);
                if ( ret < 0 )
                        return ret;
        }

        dst->vlan_num_is_set = src->vlan_num_is_set;

        dst->vlan_num = src->vlan_num;

        if ( src->address ) {
                ret = prelude_string_copy(src->address, dst->address);
                if ( ret < 0 )
                        return ret;
        }

        if ( dst->netmask ) {
                prelude_string_destroy(dst->netmask);
                dst->netmask = NULL;
        }

        if ( src->netmask ) {
                ret = prelude_string_clone(src->netmask, &dst->netmask);
                if ( ret < 0 )
                        return ret;
        }

        return 0;
}

/**
 * idmef_address_clone:
 * @src: Object to be cloned.
 * @dst: Address where to store the pointer to the cloned object.
 *
 * Create a copy of @src, and store it in @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_address_clone(idmef_address_t *src, idmef_address_t **dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = idmef_address_new(dst);
        if ( ret < 0 )
                return ret;

        return idmef_address_copy(src, *dst);
}

/**
 * idmef_address_compare:
 * @obj1: Object to compare with @obj2.
 * @obj2: Object to compare with @obj1.
 *
 * Compare @obj1 with @obj2.
 *
 * Returns: 0 on match, a negative value on comparison failure.
 */
int idmef_address_compare(const idmef_address_t *obj1, const idmef_address_t *obj2)
{
        int ret = 0;

        if ( obj1 == NULL && obj2 == NULL )
                return 0;

        else if ( obj1 == NULL || obj2 == NULL )
                return -1;

        ret = prelude_string_compare(obj1->ident, obj2->ident);
        if ( ret != 0 )
                return ret;

        if ( obj1->category != obj2->category )
                return -1;

        ret = prelude_string_compare(obj1->vlan_name, obj2->vlan_name);
        if ( ret != 0 )
                return ret;

        if ( obj1->vlan_num_is_set != obj2->vlan_num_is_set )
                return -1;

        if ( obj1->vlan_num_is_set && obj1->vlan_num != obj2->vlan_num )
                return -1;

        ret = prelude_string_compare(obj1->address, obj2->address);
        if ( ret != 0 )
                return ret;

        ret = prelude_string_compare(obj1->netmask, obj2->netmask);
        if ( ret != 0 )
                return ret;

        return ret;
}

/**
 * idmef_process_new:
 * @ret: Pointer where to store the created #idmef_process_t object.
 *
 * Create a new #idmef_process_t object.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_process_new(idmef_process_t **ret)
{
        *ret = calloc(1, sizeof(**ret));
        if ( ! *ret )
                return prelude_error_from_errno(errno);

        (*ret)->_idmef_object_id = IDMEF_CLASS_ID_PROCESS;

        (*ret)->refcount = 1;

        prelude_list_init(&(*ret)->arg_list);


        prelude_list_init(&(*ret)->env_list);


        {
                int retval = prelude_string_new(&(*ret)->name);

                if ( retval < 0 ) {
                        idmef_process_destroy(*ret);
                        *ret = NULL;
                        return retval;
                }
        }

        return 0;

}

/**
 * idmef_process_ref:
 * @process: pointer to a #idmef_process_t object.
 *
 * Increase @process reference count, so that it can be referenced
 * multiple time.
 *
 * Returns: a pointer to @process.
 */
idmef_process_t *idmef_process_ref(idmef_process_t *process)
{
        prelude_return_val_if_fail(process, NULL);
        process->refcount++;

        return process;
}

int _idmef_process_get_child(void *p, idmef_class_child_id_t child, void **childptr)
{
        idmef_process_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));
        *childptr = NULL;

        switch ( child ) {

                case 0:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->ident, TRUE);
                case 1:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->name, TRUE);
                case 2:
                       return (ptr->pid_is_set) ? idmef_value_new_uint32((idmef_value_t **) childptr, ptr->pid) : 0;

                case 3:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->path, TRUE);
                case 4:
                        *childptr = &ptr->arg_list;
                        return 0;

                case 5:
                        *childptr = &ptr->env_list;
                        return 0;

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_process_new_child(void *p, idmef_class_child_id_t child, int n, void **ret)
{
        idmef_process_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        return idmef_process_new_ident(ptr, (prelude_string_t **) ret);

                case 1:
                        return idmef_process_new_name(ptr, (prelude_string_t **) ret);

                case 2:
                        return idmef_process_new_pid(ptr, (uint32_t **) ret);

                case 3:
                        return idmef_process_new_path(ptr, (prelude_string_t **) ret);

                case 4: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n == IDMEF_LIST_APPEND || n == IDMEF_LIST_PREPEND )
                               return idmef_process_new_arg(ptr, (prelude_string_t **) ret, n);

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->arg_list, tmp) {
                                       if ( i++ == n ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->arg_list, tmp) {
                                       if ( i++ == pos ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }

                        return idmef_process_new_arg(ptr, (prelude_string_t **) ret, n);
                }

                case 5: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n == IDMEF_LIST_APPEND || n == IDMEF_LIST_PREPEND )
                               return idmef_process_new_env(ptr, (prelude_string_t **) ret, n);

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->env_list, tmp) {
                                       if ( i++ == n ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->env_list, tmp) {
                                       if ( i++ == pos ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }

                        return idmef_process_new_env(ptr, (prelude_string_t **) ret, n);
                }

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_process_destroy_child(void *p, idmef_class_child_id_t child, int n)
{
        idmef_process_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        if ( ptr->ident ) {
                                prelude_string_destroy(ptr->ident);
                                ptr->ident = NULL;
                        }

                        return 0;

                case 1:
                        if ( ptr->name ) {
                                prelude_string_destroy(ptr->name);
                                ptr->name = NULL;
                        }

                        return 0;

                case 2:
                        ptr->pid_is_set = 0;
                        return 0;

                case 3:
                        if ( ptr->path ) {
                                prelude_string_destroy(ptr->path);
                                ptr->path = NULL;
                        }

                        return 0;

                case 4: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->arg_list, tmp) {
                                       if ( i++ == n ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               prelude_string_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->arg_list, tmp) {
                                       if ( i++ == pos ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               prelude_string_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }
                }

                case 5: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->env_list, tmp) {
                                       if ( i++ == n ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               prelude_string_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->env_list, tmp) {
                                       if ( i++ == pos ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               prelude_string_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }
                }

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

static void idmef_process_destroy_internal(idmef_process_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( ptr->ident ) {
                prelude_string_destroy(ptr->ident);
                ptr->ident = NULL;
        }

        if ( ptr->name ) {
                prelude_string_destroy(ptr->name);
                ptr->name = NULL;
        }

        if ( ptr->path ) {
                prelude_string_destroy(ptr->path);
                ptr->path = NULL;
        }

        {
                prelude_list_t *n, *tmp;
                prelude_string_t *entry;

                prelude_list_for_each_safe(&ptr->arg_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        prelude_list_del_init(tmp);
                        prelude_string_destroy(entry);
                }
        }

        {
                prelude_list_t *n, *tmp;
                prelude_string_t *entry;

                prelude_list_for_each_safe(&ptr->env_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        prelude_list_del_init(tmp);
                        prelude_string_destroy(entry);
                }
        }


        /* free() should be done by the caller */
}

/**
 * idmef_process_destroy:
 * @ptr: pointer to a #idmef_process_t object.
 *
 * Destroy @ptr and all of it's children.
 * The objects are only destroyed if their reference count reach zero.
 */

void idmef_process_destroy(idmef_process_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( --ptr->refcount )
                return;

        idmef_process_destroy_internal(ptr);
        free(ptr);
}

/**
 * idmef_process_get_ident:
 * @ptr: pointer to a #idmef_process_t object.
 *
 * Get ident children of the #idmef_process_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_process_get_ident(idmef_process_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->ident;
}

/**
 * idmef_process_set_ident:
 * @ptr: pointer to a #idmef_process_t object.
 * @ident: pointer to a #prelude_string_t object.
 *
 * Set @ident object as a children of @ptr.
 * if @ptr already contain an @ident object, then it is destroyed,
 * and updated to point to the provided @ident object.
 */

void idmef_process_set_ident(idmef_process_t *ptr, prelude_string_t *ident)
{
        prelude_return_if_fail(ptr);

        if ( ptr->ident )
                prelude_string_destroy(ptr->ident);

        ptr->ident = ident;
}

/**
 * idmef_process_new_ident:
 * @ptr: pointer to a #idmef_process_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new ident object, children of #idmef_process_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_process_new_ident(idmef_process_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->ident ) {
                retval = prelude_string_new(&ptr->ident);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->ident;
        return 0;
}

/**
 * idmef_process_get_name:
 * @ptr: pointer to a #idmef_process_t object.
 *
 * Get name children of the #idmef_process_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_process_get_name(idmef_process_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->name;
}

/**
 * idmef_process_set_name:
 * @ptr: pointer to a #idmef_process_t object.
 * @name: pointer to a #prelude_string_t object.
 *
 * Set @name object as a children of @ptr.
 * if @ptr already contain an @name object, then it is destroyed,
 * and updated to point to the provided @name object.
 */

void idmef_process_set_name(idmef_process_t *ptr, prelude_string_t *name)
{
        prelude_return_if_fail(ptr);

        if ( ptr->name )
                prelude_string_destroy(ptr->name);

        ptr->name = name;
}

/**
 * idmef_process_new_name:
 * @ptr: pointer to a #idmef_process_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new name object, children of #idmef_process_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_process_new_name(idmef_process_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->name ) {
                retval = prelude_string_new(&ptr->name);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->name;
        return 0;
}

/**
 * idmef_process_get_pid:
 * @ptr: pointer to a #idmef_process_t object.
 *
 * Get pid children of the #idmef_process_t object.
 *
 * Returns: a pointer to a uint32_t object, or NULL if the children object is not set.
 */
uint32_t *idmef_process_get_pid(idmef_process_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->pid_is_set ? &ptr->pid : NULL;
}

/**
 * idmef_process_set_pid:
 * @ptr: pointer to a #idmef_process_t object.
 * @pid: pointer to a #uint32_t object.
 *
 * Set @pid object as a children of @ptr.
 * if @ptr already contain an @pid object, then it is destroyed,
 * and updated to point to the provided @pid object.
 */

void idmef_process_set_pid(idmef_process_t *ptr, uint32_t pid)
{
        prelude_return_if_fail(ptr);
        ptr->pid = pid;
        ptr->pid_is_set = 1;
}


void idmef_process_unset_pid(idmef_process_t *ptr)
{
        prelude_return_if_fail(ptr);
        ptr->pid_is_set = 0;
}


/**
 * idmef_process_new_pid:
 * @ptr: pointer to a #idmef_process_t object.
 * @ret: pointer to an address where to store the created #uint32_t object.
 *
 * Create a new pid object, children of #idmef_process_t.
 * If @ptr already contain a #uint32_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_process_new_pid(idmef_process_t *ptr, uint32_t **ret)
{
        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));
        ptr->pid_is_set = 1;

        *ret = &ptr->pid;
        return 0;
}

/**
 * idmef_process_get_path:
 * @ptr: pointer to a #idmef_process_t object.
 *
 * Get path children of the #idmef_process_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_process_get_path(idmef_process_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->path;
}

/**
 * idmef_process_set_path:
 * @ptr: pointer to a #idmef_process_t object.
 * @path: pointer to a #prelude_string_t object.
 *
 * Set @path object as a children of @ptr.
 * if @ptr already contain an @path object, then it is destroyed,
 * and updated to point to the provided @path object.
 */

void idmef_process_set_path(idmef_process_t *ptr, prelude_string_t *path)
{
        prelude_return_if_fail(ptr);

        if ( ptr->path )
                prelude_string_destroy(ptr->path);

        ptr->path = path;
}

/**
 * idmef_process_new_path:
 * @ptr: pointer to a #idmef_process_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new path object, children of #idmef_process_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_process_new_path(idmef_process_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->path ) {
                retval = prelude_string_new(&ptr->path);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->path;
        return 0;
}

/**
 * idmef_process_get_next_arg:
 * @process: pointer to a #idmef_process_t object.
 * @prelude_string_cur: pointer to a #prelude_string_t object.
 *
 * Get the next #prelude_string_t object listed in @ptr.
 * When iterating over the prelude_string_t object listed in @ptr,
 * @object should be set to the latest returned #prelude_string_t object.
 *
 * Returns: the next #prelude_string_t in the list.
 */
prelude_string_t *idmef_process_get_next_arg(idmef_process_t *process, prelude_string_t *prelude_string_cur)
{
        prelude_list_t *tmp = (prelude_string_cur) ? &((prelude_linked_object_t *) prelude_string_cur)->_list : NULL;

        prelude_return_val_if_fail(process, NULL);

        prelude_list_for_each_continue(&process->arg_list, tmp)
                return prelude_linked_object_get_object(tmp);

        return NULL;
}


/**
 * idmef_process_set_arg:
 * @ptr: pointer to a #idmef_process_t object.
 * @object: pointer to a #prelude_string_t object.
 * @pos: Position in the list.
 *
 * Add @object to position @pos of @ptr list of #prelude_string_t object.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 */
void idmef_process_set_arg(idmef_process_t *ptr, prelude_string_t *object, int pos)
{
        prelude_return_if_fail(ptr);
        prelude_return_if_fail(object);

        if ( ! prelude_list_is_empty(&((prelude_linked_object_t *) object)->_list) )
                prelude_list_del_init(&((prelude_linked_object_t *) object)->_list);

        list_insert(&ptr->arg_list, &((prelude_linked_object_t *) object)->_list, pos);
}


/**
 * idmef_process_new_arg:
 * @ptr: pointer to a #idmef_process_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 * @pos: position in the list.
 *
 * Create a new #prelude_string_t children of @ptr, and add it to position @pos of
 * @ptr list of #prelude_string_t object. The created #prelude_string_t object is
 * stored in @ret.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_process_new_arg(idmef_process_t *ptr, prelude_string_t **ret, int pos)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        retval = prelude_string_new(ret);
        if ( retval < 0 )
                return retval;

        list_insert(&ptr->arg_list, &((prelude_linked_object_t *)(*ret))->_list, pos);

        return 0;
}


/**
 * idmef_process_get_next_env:
 * @process: pointer to a #idmef_process_t object.
 * @prelude_string_cur: pointer to a #prelude_string_t object.
 *
 * Get the next #prelude_string_t object listed in @ptr.
 * When iterating over the prelude_string_t object listed in @ptr,
 * @object should be set to the latest returned #prelude_string_t object.
 *
 * Returns: the next #prelude_string_t in the list.
 */
prelude_string_t *idmef_process_get_next_env(idmef_process_t *process, prelude_string_t *prelude_string_cur)
{
        prelude_list_t *tmp = (prelude_string_cur) ? &((prelude_linked_object_t *) prelude_string_cur)->_list : NULL;

        prelude_return_val_if_fail(process, NULL);

        prelude_list_for_each_continue(&process->env_list, tmp)
                return prelude_linked_object_get_object(tmp);

        return NULL;
}


/**
 * idmef_process_set_env:
 * @ptr: pointer to a #idmef_process_t object.
 * @object: pointer to a #prelude_string_t object.
 * @pos: Position in the list.
 *
 * Add @object to position @pos of @ptr list of #prelude_string_t object.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 */
void idmef_process_set_env(idmef_process_t *ptr, prelude_string_t *object, int pos)
{
        prelude_return_if_fail(ptr);
        prelude_return_if_fail(object);

        if ( ! prelude_list_is_empty(&((prelude_linked_object_t *) object)->_list) )
                prelude_list_del_init(&((prelude_linked_object_t *) object)->_list);

        list_insert(&ptr->env_list, &((prelude_linked_object_t *) object)->_list, pos);
}


/**
 * idmef_process_new_env:
 * @ptr: pointer to a #idmef_process_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 * @pos: position in the list.
 *
 * Create a new #prelude_string_t children of @ptr, and add it to position @pos of
 * @ptr list of #prelude_string_t object. The created #prelude_string_t object is
 * stored in @ret.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_process_new_env(idmef_process_t *ptr, prelude_string_t **ret, int pos)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        retval = prelude_string_new(ret);
        if ( retval < 0 )
                return retval;

        list_insert(&ptr->env_list, &((prelude_linked_object_t *)(*ret))->_list, pos);

        return 0;
}


/**
 * idmef_process_copy:
 * @src: Source of the copy.
 * @dst: Where to copy the object.
 *
 * Copy a new #idmef_process_t object from @src to @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_process_copy(const idmef_process_t *src, idmef_process_t *dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));
        prelude_return_val_if_fail(dst, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = 0;

        if ( dst->ident ) {
                prelude_string_destroy(dst->ident);
                dst->ident = NULL;
        }

        if ( src->ident ) {
                ret = prelude_string_clone(src->ident, &dst->ident);
                if ( ret < 0 )
                        return ret;
        }

        if ( src->name ) {
                ret = prelude_string_copy(src->name, dst->name);
                if ( ret < 0 )
                        return ret;
        }

        dst->pid_is_set = src->pid_is_set;

        dst->pid = src->pid;

        if ( dst->path ) {
                prelude_string_destroy(dst->path);
                dst->path = NULL;
        }

        if ( src->path ) {
                ret = prelude_string_clone(src->path, &dst->path);
                if ( ret < 0 )
                        return ret;
        }

        {
                prelude_list_t *n, *tmp;
                prelude_string_t *entry, *new;

                prelude_list_for_each_safe(&dst->arg_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        prelude_string_destroy(entry);
                }

                prelude_list_for_each_safe(&src->arg_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        prelude_string_clone(entry, &new);
                        prelude_list_add_tail(&dst->arg_list, &((prelude_linked_object_t *) new)->_list);
                }
        }

        {
                prelude_list_t *n, *tmp;
                prelude_string_t *entry, *new;

                prelude_list_for_each_safe(&dst->env_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        prelude_string_destroy(entry);
                }

                prelude_list_for_each_safe(&src->env_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        prelude_string_clone(entry, &new);
                        prelude_list_add_tail(&dst->env_list, &((prelude_linked_object_t *) new)->_list);
                }
        }

        return 0;
}

/**
 * idmef_process_clone:
 * @src: Object to be cloned.
 * @dst: Address where to store the pointer to the cloned object.
 *
 * Create a copy of @src, and store it in @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_process_clone(idmef_process_t *src, idmef_process_t **dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = idmef_process_new(dst);
        if ( ret < 0 )
                return ret;

        return idmef_process_copy(src, *dst);
}

/**
 * idmef_process_compare:
 * @obj1: Object to compare with @obj2.
 * @obj2: Object to compare with @obj1.
 *
 * Compare @obj1 with @obj2.
 *
 * Returns: 0 on match, a negative value on comparison failure.
 */
int idmef_process_compare(const idmef_process_t *obj1, const idmef_process_t *obj2)
{
        int ret = 0;

        if ( obj1 == NULL && obj2 == NULL )
                return 0;

        else if ( obj1 == NULL || obj2 == NULL )
                return -1;

        ret = prelude_string_compare(obj1->ident, obj2->ident);
        if ( ret != 0 )
                return ret;

        ret = prelude_string_compare(obj1->name, obj2->name);
        if ( ret != 0 )
                return ret;

        if ( obj1->pid_is_set != obj2->pid_is_set )
                return -1;

        if ( obj1->pid_is_set && obj1->pid != obj2->pid )
                return -1;

        ret = prelude_string_compare(obj1->path, obj2->path);
        if ( ret != 0 )
                return ret;

        {
                prelude_list_t *tmp1, *tmp2;
                prelude_string_t *entry1, *entry2;

                tmp1 = tmp2 = NULL;
                do {
                        entry1 = entry2 = NULL;

                        prelude_list_for_each_continue(&obj1->arg_list, tmp1) {
                                entry1 = prelude_linked_object_get_object(tmp1);
                                break;
                        }

                        prelude_list_for_each_continue(&obj2->arg_list, tmp2) {
                                entry2 = prelude_linked_object_get_object(tmp2);
                                break;
                        }

                        ret = prelude_string_compare(entry1, entry2);
                        if ( ret != 0 )
                                return ret;

                } while ( entry1 && entry2 );
        }

        {
                prelude_list_t *tmp1, *tmp2;
                prelude_string_t *entry1, *entry2;

                tmp1 = tmp2 = NULL;
                do {
                        entry1 = entry2 = NULL;

                        prelude_list_for_each_continue(&obj1->env_list, tmp1) {
                                entry1 = prelude_linked_object_get_object(tmp1);
                                break;
                        }

                        prelude_list_for_each_continue(&obj2->env_list, tmp2) {
                                entry2 = prelude_linked_object_get_object(tmp2);
                                break;
                        }

                        ret = prelude_string_compare(entry1, entry2);
                        if ( ret != 0 )
                                return ret;

                } while ( entry1 && entry2 );
        }

        return ret;
}

/**
 * idmef_web_service_new:
 * @ret: Pointer where to store the created #idmef_web_service_t object.
 *
 * Create a new #idmef_web_service_t object.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_web_service_new(idmef_web_service_t **ret)
{
        *ret = calloc(1, sizeof(**ret));
        if ( ! *ret )
                return prelude_error_from_errno(errno);

        (*ret)->_idmef_object_id = IDMEF_CLASS_ID_WEB_SERVICE;

        (*ret)->refcount = 1;

        prelude_list_init(&(*ret)->arg_list);


        {
                int retval = prelude_string_new(&(*ret)->url);

                if ( retval < 0 ) {
                        idmef_web_service_destroy(*ret);
                        *ret = NULL;
                        return retval;
                }
        }

        return 0;

}

/**
 * idmef_web_service_ref:
 * @web_service: pointer to a #idmef_web_service_t object.
 *
 * Increase @web_service reference count, so that it can be referenced
 * multiple time.
 *
 * Returns: a pointer to @web_service.
 */
idmef_web_service_t *idmef_web_service_ref(idmef_web_service_t *web_service)
{
        prelude_return_val_if_fail(web_service, NULL);
        web_service->refcount++;

        return web_service;
}

int _idmef_web_service_get_child(void *p, idmef_class_child_id_t child, void **childptr)
{
        idmef_web_service_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));
        *childptr = NULL;

        switch ( child ) {

                case 0:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->url, TRUE);
                case 1:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->cgi, TRUE);
                case 2:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->http_method, TRUE);
                case 3:
                        *childptr = &ptr->arg_list;
                        return 0;

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_web_service_new_child(void *p, idmef_class_child_id_t child, int n, void **ret)
{
        idmef_web_service_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        return idmef_web_service_new_url(ptr, (prelude_string_t **) ret);

                case 1:
                        return idmef_web_service_new_cgi(ptr, (prelude_string_t **) ret);

                case 2:
                        return idmef_web_service_new_http_method(ptr, (prelude_string_t **) ret);

                case 3: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n == IDMEF_LIST_APPEND || n == IDMEF_LIST_PREPEND )
                               return idmef_web_service_new_arg(ptr, (prelude_string_t **) ret, n);

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->arg_list, tmp) {
                                       if ( i++ == n ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->arg_list, tmp) {
                                       if ( i++ == pos ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }

                        return idmef_web_service_new_arg(ptr, (prelude_string_t **) ret, n);
                }

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_web_service_destroy_child(void *p, idmef_class_child_id_t child, int n)
{
        idmef_web_service_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        if ( ptr->url ) {
                                prelude_string_destroy(ptr->url);
                                ptr->url = NULL;
                        }

                        return 0;

                case 1:
                        if ( ptr->cgi ) {
                                prelude_string_destroy(ptr->cgi);
                                ptr->cgi = NULL;
                        }

                        return 0;

                case 2:
                        if ( ptr->http_method ) {
                                prelude_string_destroy(ptr->http_method);
                                ptr->http_method = NULL;
                        }

                        return 0;

                case 3: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->arg_list, tmp) {
                                       if ( i++ == n ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               prelude_string_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->arg_list, tmp) {
                                       if ( i++ == pos ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               prelude_string_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }
                }

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

static void idmef_web_service_destroy_internal(idmef_web_service_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( ptr->url ) {
                prelude_string_destroy(ptr->url);
                ptr->url = NULL;
        }

        if ( ptr->cgi ) {
                prelude_string_destroy(ptr->cgi);
                ptr->cgi = NULL;
        }

        if ( ptr->http_method ) {
                prelude_string_destroy(ptr->http_method);
                ptr->http_method = NULL;
        }

        {
                prelude_list_t *n, *tmp;
                prelude_string_t *entry;

                prelude_list_for_each_safe(&ptr->arg_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        prelude_list_del_init(tmp);
                        prelude_string_destroy(entry);
                }
        }


        /* free() should be done by the caller */
}

/**
 * idmef_web_service_destroy:
 * @ptr: pointer to a #idmef_web_service_t object.
 *
 * Destroy @ptr and all of it's children.
 * The objects are only destroyed if their reference count reach zero.
 */

void idmef_web_service_destroy(idmef_web_service_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( --ptr->refcount )
                return;

        idmef_web_service_destroy_internal(ptr);
        free(ptr);
}

/**
 * idmef_web_service_get_url:
 * @ptr: pointer to a #idmef_web_service_t object.
 *
 * Get url children of the #idmef_web_service_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_web_service_get_url(idmef_web_service_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->url;
}

/**
 * idmef_web_service_set_url:
 * @ptr: pointer to a #idmef_web_service_t object.
 * @url: pointer to a #prelude_string_t object.
 *
 * Set @url object as a children of @ptr.
 * if @ptr already contain an @url object, then it is destroyed,
 * and updated to point to the provided @url object.
 */

void idmef_web_service_set_url(idmef_web_service_t *ptr, prelude_string_t *url)
{
        prelude_return_if_fail(ptr);

        if ( ptr->url )
                prelude_string_destroy(ptr->url);

        ptr->url = url;
}

/**
 * idmef_web_service_new_url:
 * @ptr: pointer to a #idmef_web_service_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new url object, children of #idmef_web_service_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_web_service_new_url(idmef_web_service_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->url ) {
                retval = prelude_string_new(&ptr->url);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->url;
        return 0;
}

/**
 * idmef_web_service_get_cgi:
 * @ptr: pointer to a #idmef_web_service_t object.
 *
 * Get cgi children of the #idmef_web_service_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_web_service_get_cgi(idmef_web_service_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->cgi;
}

/**
 * idmef_web_service_set_cgi:
 * @ptr: pointer to a #idmef_web_service_t object.
 * @cgi: pointer to a #prelude_string_t object.
 *
 * Set @cgi object as a children of @ptr.
 * if @ptr already contain an @cgi object, then it is destroyed,
 * and updated to point to the provided @cgi object.
 */

void idmef_web_service_set_cgi(idmef_web_service_t *ptr, prelude_string_t *cgi)
{
        prelude_return_if_fail(ptr);

        if ( ptr->cgi )
                prelude_string_destroy(ptr->cgi);

        ptr->cgi = cgi;
}

/**
 * idmef_web_service_new_cgi:
 * @ptr: pointer to a #idmef_web_service_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new cgi object, children of #idmef_web_service_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_web_service_new_cgi(idmef_web_service_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->cgi ) {
                retval = prelude_string_new(&ptr->cgi);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->cgi;
        return 0;
}

/**
 * idmef_web_service_get_http_method:
 * @ptr: pointer to a #idmef_web_service_t object.
 *
 * Get http_method children of the #idmef_web_service_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_web_service_get_http_method(idmef_web_service_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->http_method;
}

/**
 * idmef_web_service_set_http_method:
 * @ptr: pointer to a #idmef_web_service_t object.
 * @http_method: pointer to a #prelude_string_t object.
 *
 * Set @http_method object as a children of @ptr.
 * if @ptr already contain an @http_method object, then it is destroyed,
 * and updated to point to the provided @http_method object.
 */

void idmef_web_service_set_http_method(idmef_web_service_t *ptr, prelude_string_t *http_method)
{
        prelude_return_if_fail(ptr);

        if ( ptr->http_method )
                prelude_string_destroy(ptr->http_method);

        ptr->http_method = http_method;
}

/**
 * idmef_web_service_new_http_method:
 * @ptr: pointer to a #idmef_web_service_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new http_method object, children of #idmef_web_service_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_web_service_new_http_method(idmef_web_service_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->http_method ) {
                retval = prelude_string_new(&ptr->http_method);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->http_method;
        return 0;
}

/**
 * idmef_web_service_get_next_arg:
 * @web_service: pointer to a #idmef_web_service_t object.
 * @prelude_string_cur: pointer to a #prelude_string_t object.
 *
 * Get the next #prelude_string_t object listed in @ptr.
 * When iterating over the prelude_string_t object listed in @ptr,
 * @object should be set to the latest returned #prelude_string_t object.
 *
 * Returns: the next #prelude_string_t in the list.
 */
prelude_string_t *idmef_web_service_get_next_arg(idmef_web_service_t *web_service, prelude_string_t *prelude_string_cur)
{
        prelude_list_t *tmp = (prelude_string_cur) ? &((prelude_linked_object_t *) prelude_string_cur)->_list : NULL;

        prelude_return_val_if_fail(web_service, NULL);

        prelude_list_for_each_continue(&web_service->arg_list, tmp)
                return prelude_linked_object_get_object(tmp);

        return NULL;
}


/**
 * idmef_web_service_set_arg:
 * @ptr: pointer to a #idmef_web_service_t object.
 * @object: pointer to a #prelude_string_t object.
 * @pos: Position in the list.
 *
 * Add @object to position @pos of @ptr list of #prelude_string_t object.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 */
void idmef_web_service_set_arg(idmef_web_service_t *ptr, prelude_string_t *object, int pos)
{
        prelude_return_if_fail(ptr);
        prelude_return_if_fail(object);

        if ( ! prelude_list_is_empty(&((prelude_linked_object_t *) object)->_list) )
                prelude_list_del_init(&((prelude_linked_object_t *) object)->_list);

        list_insert(&ptr->arg_list, &((prelude_linked_object_t *) object)->_list, pos);
}


/**
 * idmef_web_service_new_arg:
 * @ptr: pointer to a #idmef_web_service_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 * @pos: position in the list.
 *
 * Create a new #prelude_string_t children of @ptr, and add it to position @pos of
 * @ptr list of #prelude_string_t object. The created #prelude_string_t object is
 * stored in @ret.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_web_service_new_arg(idmef_web_service_t *ptr, prelude_string_t **ret, int pos)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        retval = prelude_string_new(ret);
        if ( retval < 0 )
                return retval;

        list_insert(&ptr->arg_list, &((prelude_linked_object_t *)(*ret))->_list, pos);

        return 0;
}


/**
 * idmef_web_service_copy:
 * @src: Source of the copy.
 * @dst: Where to copy the object.
 *
 * Copy a new #idmef_web_service_t object from @src to @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_web_service_copy(const idmef_web_service_t *src, idmef_web_service_t *dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));
        prelude_return_val_if_fail(dst, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = 0;

        if ( src->url ) {
                ret = prelude_string_copy(src->url, dst->url);
                if ( ret < 0 )
                        return ret;
        }

        if ( dst->cgi ) {
                prelude_string_destroy(dst->cgi);
                dst->cgi = NULL;
        }

        if ( src->cgi ) {
                ret = prelude_string_clone(src->cgi, &dst->cgi);
                if ( ret < 0 )
                        return ret;
        }

        if ( dst->http_method ) {
                prelude_string_destroy(dst->http_method);
                dst->http_method = NULL;
        }

        if ( src->http_method ) {
                ret = prelude_string_clone(src->http_method, &dst->http_method);
                if ( ret < 0 )
                        return ret;
        }

        {
                prelude_list_t *n, *tmp;
                prelude_string_t *entry, *new;

                prelude_list_for_each_safe(&dst->arg_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        prelude_string_destroy(entry);
                }

                prelude_list_for_each_safe(&src->arg_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        prelude_string_clone(entry, &new);
                        prelude_list_add_tail(&dst->arg_list, &((prelude_linked_object_t *) new)->_list);
                }
        }

        return 0;
}

/**
 * idmef_web_service_clone:
 * @src: Object to be cloned.
 * @dst: Address where to store the pointer to the cloned object.
 *
 * Create a copy of @src, and store it in @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_web_service_clone(idmef_web_service_t *src, idmef_web_service_t **dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = idmef_web_service_new(dst);
        if ( ret < 0 )
                return ret;

        return idmef_web_service_copy(src, *dst);
}

/**
 * idmef_web_service_compare:
 * @obj1: Object to compare with @obj2.
 * @obj2: Object to compare with @obj1.
 *
 * Compare @obj1 with @obj2.
 *
 * Returns: 0 on match, a negative value on comparison failure.
 */
int idmef_web_service_compare(const idmef_web_service_t *obj1, const idmef_web_service_t *obj2)
{
        int ret = 0;

        if ( obj1 == NULL && obj2 == NULL )
                return 0;

        else if ( obj1 == NULL || obj2 == NULL )
                return -1;

        ret = prelude_string_compare(obj1->url, obj2->url);
        if ( ret != 0 )
                return ret;

        ret = prelude_string_compare(obj1->cgi, obj2->cgi);
        if ( ret != 0 )
                return ret;

        ret = prelude_string_compare(obj1->http_method, obj2->http_method);
        if ( ret != 0 )
                return ret;

        {
                prelude_list_t *tmp1, *tmp2;
                prelude_string_t *entry1, *entry2;

                tmp1 = tmp2 = NULL;
                do {
                        entry1 = entry2 = NULL;

                        prelude_list_for_each_continue(&obj1->arg_list, tmp1) {
                                entry1 = prelude_linked_object_get_object(tmp1);
                                break;
                        }

                        prelude_list_for_each_continue(&obj2->arg_list, tmp2) {
                                entry2 = prelude_linked_object_get_object(tmp2);
                                break;
                        }

                        ret = prelude_string_compare(entry1, entry2);
                        if ( ret != 0 )
                                return ret;

                } while ( entry1 && entry2 );
        }

        return ret;
}

/**
 * idmef_snmp_service_new:
 * @ret: Pointer where to store the created #idmef_snmp_service_t object.
 *
 * Create a new #idmef_snmp_service_t object.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_snmp_service_new(idmef_snmp_service_t **ret)
{
        *ret = calloc(1, sizeof(**ret));
        if ( ! *ret )
                return prelude_error_from_errno(errno);

        (*ret)->_idmef_object_id = IDMEF_CLASS_ID_SNMP_SERVICE;

        (*ret)->refcount = 1;

        return 0;

}

/**
 * idmef_snmp_service_ref:
 * @snmp_service: pointer to a #idmef_snmp_service_t object.
 *
 * Increase @snmp_service reference count, so that it can be referenced
 * multiple time.
 *
 * Returns: a pointer to @snmp_service.
 */
idmef_snmp_service_t *idmef_snmp_service_ref(idmef_snmp_service_t *snmp_service)
{
        prelude_return_val_if_fail(snmp_service, NULL);
        snmp_service->refcount++;

        return snmp_service;
}

int _idmef_snmp_service_get_child(void *p, idmef_class_child_id_t child, void **childptr)
{
        idmef_snmp_service_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));
        *childptr = NULL;

        switch ( child ) {

                case 0:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->oid, TRUE);
                case 1:
                       return (ptr->message_processing_model_is_set) ? idmef_value_new_uint32((idmef_value_t **) childptr, ptr->message_processing_model) : 0;

                case 2:
                       return (ptr->security_model_is_set) ? idmef_value_new_uint32((idmef_value_t **) childptr, ptr->security_model) : 0;

                case 3:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->security_name, TRUE);
                case 4:
                       return (ptr->security_level_is_set) ? idmef_value_new_uint32((idmef_value_t **) childptr, ptr->security_level) : 0;

                case 5:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->context_name, TRUE);
                case 6:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->context_engine_id, TRUE);
                case 7:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->command, TRUE);
                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_snmp_service_new_child(void *p, idmef_class_child_id_t child, int n, void **ret)
{
        idmef_snmp_service_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        return idmef_snmp_service_new_oid(ptr, (prelude_string_t **) ret);

                case 1:
                        return idmef_snmp_service_new_message_processing_model(ptr, (uint32_t **) ret);

                case 2:
                        return idmef_snmp_service_new_security_model(ptr, (uint32_t **) ret);

                case 3:
                        return idmef_snmp_service_new_security_name(ptr, (prelude_string_t **) ret);

                case 4:
                        return idmef_snmp_service_new_security_level(ptr, (uint32_t **) ret);

                case 5:
                        return idmef_snmp_service_new_context_name(ptr, (prelude_string_t **) ret);

                case 6:
                        return idmef_snmp_service_new_context_engine_id(ptr, (prelude_string_t **) ret);

                case 7:
                        return idmef_snmp_service_new_command(ptr, (prelude_string_t **) ret);

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_snmp_service_destroy_child(void *p, idmef_class_child_id_t child, int n)
{
        idmef_snmp_service_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        if ( ptr->oid ) {
                                prelude_string_destroy(ptr->oid);
                                ptr->oid = NULL;
                        }

                        return 0;

                case 1:
                        ptr->message_processing_model_is_set = 0;
                        return 0;

                case 2:
                        ptr->security_model_is_set = 0;
                        return 0;

                case 3:
                        if ( ptr->security_name ) {
                                prelude_string_destroy(ptr->security_name);
                                ptr->security_name = NULL;
                        }

                        return 0;

                case 4:
                        ptr->security_level_is_set = 0;
                        return 0;

                case 5:
                        if ( ptr->context_name ) {
                                prelude_string_destroy(ptr->context_name);
                                ptr->context_name = NULL;
                        }

                        return 0;

                case 6:
                        if ( ptr->context_engine_id ) {
                                prelude_string_destroy(ptr->context_engine_id);
                                ptr->context_engine_id = NULL;
                        }

                        return 0;

                case 7:
                        if ( ptr->command ) {
                                prelude_string_destroy(ptr->command);
                                ptr->command = NULL;
                        }

                        return 0;

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

static void idmef_snmp_service_destroy_internal(idmef_snmp_service_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( ptr->oid ) {
                prelude_string_destroy(ptr->oid);
                ptr->oid = NULL;
        }

        if ( ptr->security_name ) {
                prelude_string_destroy(ptr->security_name);
                ptr->security_name = NULL;
        }

        if ( ptr->context_name ) {
                prelude_string_destroy(ptr->context_name);
                ptr->context_name = NULL;
        }

        if ( ptr->context_engine_id ) {
                prelude_string_destroy(ptr->context_engine_id);
                ptr->context_engine_id = NULL;
        }

        if ( ptr->command ) {
                prelude_string_destroy(ptr->command);
                ptr->command = NULL;
        }


        /* free() should be done by the caller */
}

/**
 * idmef_snmp_service_destroy:
 * @ptr: pointer to a #idmef_snmp_service_t object.
 *
 * Destroy @ptr and all of it's children.
 * The objects are only destroyed if their reference count reach zero.
 */

void idmef_snmp_service_destroy(idmef_snmp_service_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( --ptr->refcount )
                return;

        idmef_snmp_service_destroy_internal(ptr);
        free(ptr);
}

/**
 * idmef_snmp_service_get_oid:
 * @ptr: pointer to a #idmef_snmp_service_t object.
 *
 * Get oid children of the #idmef_snmp_service_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_snmp_service_get_oid(idmef_snmp_service_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->oid;
}

/**
 * idmef_snmp_service_set_oid:
 * @ptr: pointer to a #idmef_snmp_service_t object.
 * @oid: pointer to a #prelude_string_t object.
 *
 * Set @oid object as a children of @ptr.
 * if @ptr already contain an @oid object, then it is destroyed,
 * and updated to point to the provided @oid object.
 */

void idmef_snmp_service_set_oid(idmef_snmp_service_t *ptr, prelude_string_t *oid)
{
        prelude_return_if_fail(ptr);

        if ( ptr->oid )
                prelude_string_destroy(ptr->oid);

        ptr->oid = oid;
}

/**
 * idmef_snmp_service_new_oid:
 * @ptr: pointer to a #idmef_snmp_service_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new oid object, children of #idmef_snmp_service_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_snmp_service_new_oid(idmef_snmp_service_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->oid ) {
                retval = prelude_string_new(&ptr->oid);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->oid;
        return 0;
}

/**
 * idmef_snmp_service_get_message_processing_model:
 * @ptr: pointer to a #idmef_snmp_service_t object.
 *
 * Get message_processing_model children of the #idmef_snmp_service_t object.
 *
 * Returns: a pointer to a uint32_t object, or NULL if the children object is not set.
 */
uint32_t *idmef_snmp_service_get_message_processing_model(idmef_snmp_service_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->message_processing_model_is_set ? &ptr->message_processing_model : NULL;
}

/**
 * idmef_snmp_service_set_message_processing_model:
 * @ptr: pointer to a #idmef_snmp_service_t object.
 * @message_processing_model: pointer to a #uint32_t object.
 *
 * Set @message_processing_model object as a children of @ptr.
 * if @ptr already contain an @message_processing_model object, then it is destroyed,
 * and updated to point to the provided @message_processing_model object.
 */

void idmef_snmp_service_set_message_processing_model(idmef_snmp_service_t *ptr, uint32_t message_processing_model)
{
        prelude_return_if_fail(ptr);
        ptr->message_processing_model = message_processing_model;
        ptr->message_processing_model_is_set = 1;
}


void idmef_snmp_service_unset_message_processing_model(idmef_snmp_service_t *ptr)
{
        prelude_return_if_fail(ptr);
        ptr->message_processing_model_is_set = 0;
}


/**
 * idmef_snmp_service_new_message_processing_model:
 * @ptr: pointer to a #idmef_snmp_service_t object.
 * @ret: pointer to an address where to store the created #uint32_t object.
 *
 * Create a new message_processing_model object, children of #idmef_snmp_service_t.
 * If @ptr already contain a #uint32_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_snmp_service_new_message_processing_model(idmef_snmp_service_t *ptr, uint32_t **ret)
{
        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));
        ptr->message_processing_model_is_set = 1;

        *ret = &ptr->message_processing_model;
        return 0;
}

/**
 * idmef_snmp_service_get_security_model:
 * @ptr: pointer to a #idmef_snmp_service_t object.
 *
 * Get security_model children of the #idmef_snmp_service_t object.
 *
 * Returns: a pointer to a uint32_t object, or NULL if the children object is not set.
 */
uint32_t *idmef_snmp_service_get_security_model(idmef_snmp_service_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->security_model_is_set ? &ptr->security_model : NULL;
}

/**
 * idmef_snmp_service_set_security_model:
 * @ptr: pointer to a #idmef_snmp_service_t object.
 * @security_model: pointer to a #uint32_t object.
 *
 * Set @security_model object as a children of @ptr.
 * if @ptr already contain an @security_model object, then it is destroyed,
 * and updated to point to the provided @security_model object.
 */

void idmef_snmp_service_set_security_model(idmef_snmp_service_t *ptr, uint32_t security_model)
{
        prelude_return_if_fail(ptr);
        ptr->security_model = security_model;
        ptr->security_model_is_set = 1;
}


void idmef_snmp_service_unset_security_model(idmef_snmp_service_t *ptr)
{
        prelude_return_if_fail(ptr);
        ptr->security_model_is_set = 0;
}


/**
 * idmef_snmp_service_new_security_model:
 * @ptr: pointer to a #idmef_snmp_service_t object.
 * @ret: pointer to an address where to store the created #uint32_t object.
 *
 * Create a new security_model object, children of #idmef_snmp_service_t.
 * If @ptr already contain a #uint32_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_snmp_service_new_security_model(idmef_snmp_service_t *ptr, uint32_t **ret)
{
        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));
        ptr->security_model_is_set = 1;

        *ret = &ptr->security_model;
        return 0;
}

/**
 * idmef_snmp_service_get_security_name:
 * @ptr: pointer to a #idmef_snmp_service_t object.
 *
 * Get security_name children of the #idmef_snmp_service_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_snmp_service_get_security_name(idmef_snmp_service_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->security_name;
}

/**
 * idmef_snmp_service_set_security_name:
 * @ptr: pointer to a #idmef_snmp_service_t object.
 * @security_name: pointer to a #prelude_string_t object.
 *
 * Set @security_name object as a children of @ptr.
 * if @ptr already contain an @security_name object, then it is destroyed,
 * and updated to point to the provided @security_name object.
 */

void idmef_snmp_service_set_security_name(idmef_snmp_service_t *ptr, prelude_string_t *security_name)
{
        prelude_return_if_fail(ptr);

        if ( ptr->security_name )
                prelude_string_destroy(ptr->security_name);

        ptr->security_name = security_name;
}

/**
 * idmef_snmp_service_new_security_name:
 * @ptr: pointer to a #idmef_snmp_service_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new security_name object, children of #idmef_snmp_service_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_snmp_service_new_security_name(idmef_snmp_service_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->security_name ) {
                retval = prelude_string_new(&ptr->security_name);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->security_name;
        return 0;
}

/**
 * idmef_snmp_service_get_security_level:
 * @ptr: pointer to a #idmef_snmp_service_t object.
 *
 * Get security_level children of the #idmef_snmp_service_t object.
 *
 * Returns: a pointer to a uint32_t object, or NULL if the children object is not set.
 */
uint32_t *idmef_snmp_service_get_security_level(idmef_snmp_service_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->security_level_is_set ? &ptr->security_level : NULL;
}

/**
 * idmef_snmp_service_set_security_level:
 * @ptr: pointer to a #idmef_snmp_service_t object.
 * @security_level: pointer to a #uint32_t object.
 *
 * Set @security_level object as a children of @ptr.
 * if @ptr already contain an @security_level object, then it is destroyed,
 * and updated to point to the provided @security_level object.
 */

void idmef_snmp_service_set_security_level(idmef_snmp_service_t *ptr, uint32_t security_level)
{
        prelude_return_if_fail(ptr);
        ptr->security_level = security_level;
        ptr->security_level_is_set = 1;
}


void idmef_snmp_service_unset_security_level(idmef_snmp_service_t *ptr)
{
        prelude_return_if_fail(ptr);
        ptr->security_level_is_set = 0;
}


/**
 * idmef_snmp_service_new_security_level:
 * @ptr: pointer to a #idmef_snmp_service_t object.
 * @ret: pointer to an address where to store the created #uint32_t object.
 *
 * Create a new security_level object, children of #idmef_snmp_service_t.
 * If @ptr already contain a #uint32_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_snmp_service_new_security_level(idmef_snmp_service_t *ptr, uint32_t **ret)
{
        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));
        ptr->security_level_is_set = 1;

        *ret = &ptr->security_level;
        return 0;
}

/**
 * idmef_snmp_service_get_context_name:
 * @ptr: pointer to a #idmef_snmp_service_t object.
 *
 * Get context_name children of the #idmef_snmp_service_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_snmp_service_get_context_name(idmef_snmp_service_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->context_name;
}

/**
 * idmef_snmp_service_set_context_name:
 * @ptr: pointer to a #idmef_snmp_service_t object.
 * @context_name: pointer to a #prelude_string_t object.
 *
 * Set @context_name object as a children of @ptr.
 * if @ptr already contain an @context_name object, then it is destroyed,
 * and updated to point to the provided @context_name object.
 */

void idmef_snmp_service_set_context_name(idmef_snmp_service_t *ptr, prelude_string_t *context_name)
{
        prelude_return_if_fail(ptr);

        if ( ptr->context_name )
                prelude_string_destroy(ptr->context_name);

        ptr->context_name = context_name;
}

/**
 * idmef_snmp_service_new_context_name:
 * @ptr: pointer to a #idmef_snmp_service_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new context_name object, children of #idmef_snmp_service_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_snmp_service_new_context_name(idmef_snmp_service_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->context_name ) {
                retval = prelude_string_new(&ptr->context_name);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->context_name;
        return 0;
}

/**
 * idmef_snmp_service_get_context_engine_id:
 * @ptr: pointer to a #idmef_snmp_service_t object.
 *
 * Get context_engine_id children of the #idmef_snmp_service_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_snmp_service_get_context_engine_id(idmef_snmp_service_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->context_engine_id;
}

/**
 * idmef_snmp_service_set_context_engine_id:
 * @ptr: pointer to a #idmef_snmp_service_t object.
 * @context_engine_id: pointer to a #prelude_string_t object.
 *
 * Set @context_engine_id object as a children of @ptr.
 * if @ptr already contain an @context_engine_id object, then it is destroyed,
 * and updated to point to the provided @context_engine_id object.
 */

void idmef_snmp_service_set_context_engine_id(idmef_snmp_service_t *ptr, prelude_string_t *context_engine_id)
{
        prelude_return_if_fail(ptr);

        if ( ptr->context_engine_id )
                prelude_string_destroy(ptr->context_engine_id);

        ptr->context_engine_id = context_engine_id;
}

/**
 * idmef_snmp_service_new_context_engine_id:
 * @ptr: pointer to a #idmef_snmp_service_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new context_engine_id object, children of #idmef_snmp_service_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_snmp_service_new_context_engine_id(idmef_snmp_service_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->context_engine_id ) {
                retval = prelude_string_new(&ptr->context_engine_id);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->context_engine_id;
        return 0;
}

/**
 * idmef_snmp_service_get_command:
 * @ptr: pointer to a #idmef_snmp_service_t object.
 *
 * Get command children of the #idmef_snmp_service_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_snmp_service_get_command(idmef_snmp_service_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->command;
}

/**
 * idmef_snmp_service_set_command:
 * @ptr: pointer to a #idmef_snmp_service_t object.
 * @command: pointer to a #prelude_string_t object.
 *
 * Set @command object as a children of @ptr.
 * if @ptr already contain an @command object, then it is destroyed,
 * and updated to point to the provided @command object.
 */

void idmef_snmp_service_set_command(idmef_snmp_service_t *ptr, prelude_string_t *command)
{
        prelude_return_if_fail(ptr);

        if ( ptr->command )
                prelude_string_destroy(ptr->command);

        ptr->command = command;
}

/**
 * idmef_snmp_service_new_command:
 * @ptr: pointer to a #idmef_snmp_service_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new command object, children of #idmef_snmp_service_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_snmp_service_new_command(idmef_snmp_service_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->command ) {
                retval = prelude_string_new(&ptr->command);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->command;
        return 0;
}

/**
 * idmef_snmp_service_copy:
 * @src: Source of the copy.
 * @dst: Where to copy the object.
 *
 * Copy a new #idmef_snmp_service_t object from @src to @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_snmp_service_copy(const idmef_snmp_service_t *src, idmef_snmp_service_t *dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));
        prelude_return_val_if_fail(dst, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = 0;

        if ( dst->oid ) {
                prelude_string_destroy(dst->oid);
                dst->oid = NULL;
        }

        if ( src->oid ) {
                ret = prelude_string_clone(src->oid, &dst->oid);
                if ( ret < 0 )
                        return ret;
        }

        dst->message_processing_model_is_set = src->message_processing_model_is_set;

        dst->message_processing_model = src->message_processing_model;

        dst->security_model_is_set = src->security_model_is_set;

        dst->security_model = src->security_model;

        if ( dst->security_name ) {
                prelude_string_destroy(dst->security_name);
                dst->security_name = NULL;
        }

        if ( src->security_name ) {
                ret = prelude_string_clone(src->security_name, &dst->security_name);
                if ( ret < 0 )
                        return ret;
        }

        dst->security_level_is_set = src->security_level_is_set;

        dst->security_level = src->security_level;

        if ( dst->context_name ) {
                prelude_string_destroy(dst->context_name);
                dst->context_name = NULL;
        }

        if ( src->context_name ) {
                ret = prelude_string_clone(src->context_name, &dst->context_name);
                if ( ret < 0 )
                        return ret;
        }

        if ( dst->context_engine_id ) {
                prelude_string_destroy(dst->context_engine_id);
                dst->context_engine_id = NULL;
        }

        if ( src->context_engine_id ) {
                ret = prelude_string_clone(src->context_engine_id, &dst->context_engine_id);
                if ( ret < 0 )
                        return ret;
        }

        if ( dst->command ) {
                prelude_string_destroy(dst->command);
                dst->command = NULL;
        }

        if ( src->command ) {
                ret = prelude_string_clone(src->command, &dst->command);
                if ( ret < 0 )
                        return ret;
        }

        return 0;
}

/**
 * idmef_snmp_service_clone:
 * @src: Object to be cloned.
 * @dst: Address where to store the pointer to the cloned object.
 *
 * Create a copy of @src, and store it in @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_snmp_service_clone(idmef_snmp_service_t *src, idmef_snmp_service_t **dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = idmef_snmp_service_new(dst);
        if ( ret < 0 )
                return ret;

        return idmef_snmp_service_copy(src, *dst);
}

/**
 * idmef_snmp_service_compare:
 * @obj1: Object to compare with @obj2.
 * @obj2: Object to compare with @obj1.
 *
 * Compare @obj1 with @obj2.
 *
 * Returns: 0 on match, a negative value on comparison failure.
 */
int idmef_snmp_service_compare(const idmef_snmp_service_t *obj1, const idmef_snmp_service_t *obj2)
{
        int ret = 0;

        if ( obj1 == NULL && obj2 == NULL )
                return 0;

        else if ( obj1 == NULL || obj2 == NULL )
                return -1;

        ret = prelude_string_compare(obj1->oid, obj2->oid);
        if ( ret != 0 )
                return ret;

        if ( obj1->message_processing_model_is_set != obj2->message_processing_model_is_set )
                return -1;

        if ( obj1->message_processing_model_is_set && obj1->message_processing_model != obj2->message_processing_model )
                return -1;

        if ( obj1->security_model_is_set != obj2->security_model_is_set )
                return -1;

        if ( obj1->security_model_is_set && obj1->security_model != obj2->security_model )
                return -1;

        ret = prelude_string_compare(obj1->security_name, obj2->security_name);
        if ( ret != 0 )
                return ret;

        if ( obj1->security_level_is_set != obj2->security_level_is_set )
                return -1;

        if ( obj1->security_level_is_set && obj1->security_level != obj2->security_level )
                return -1;

        ret = prelude_string_compare(obj1->context_name, obj2->context_name);
        if ( ret != 0 )
                return ret;

        ret = prelude_string_compare(obj1->context_engine_id, obj2->context_engine_id);
        if ( ret != 0 )
                return ret;

        ret = prelude_string_compare(obj1->command, obj2->command);
        if ( ret != 0 )
                return ret;

        return ret;
}

/**
 * idmef_service_new:
 * @ret: Pointer where to store the created #idmef_service_t object.
 *
 * Create a new #idmef_service_t object.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_service_new(idmef_service_t **ret)
{
        *ret = calloc(1, sizeof(**ret));
        if ( ! *ret )
                return prelude_error_from_errno(errno);

        (*ret)->_idmef_object_id = IDMEF_CLASS_ID_SERVICE;

        (*ret)->refcount = 1;

        return 0;

}

/**
 * idmef_service_ref:
 * @service: pointer to a #idmef_service_t object.
 *
 * Increase @service reference count, so that it can be referenced
 * multiple time.
 *
 * Returns: a pointer to @service.
 */
idmef_service_t *idmef_service_ref(idmef_service_t *service)
{
        prelude_return_val_if_fail(service, NULL);
        service->refcount++;

        return service;
}

int _idmef_service_get_child(void *p, idmef_class_child_id_t child, void **childptr)
{
        idmef_service_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));
        *childptr = NULL;

        switch ( child ) {

                case 0:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->ident, TRUE);
                case 1:
                       return (ptr->ip_version_is_set) ? idmef_value_new_uint8((idmef_value_t **) childptr, ptr->ip_version) : 0;

                case 2:
                       return (ptr->iana_protocol_number_is_set) ? idmef_value_new_uint8((idmef_value_t **) childptr, ptr->iana_protocol_number) : 0;

                case 3:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->iana_protocol_name, TRUE);
                case 4:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->name, TRUE);
                case 5:
                       return (ptr->port_is_set) ? idmef_value_new_uint16((idmef_value_t **) childptr, ptr->port) : 0;

                case 6:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->portlist, TRUE);
                case 7:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->protocol, TRUE);
                case 8:
                        *childptr = ( ptr->type == IDMEF_SERVICE_TYPE_WEB ) ? ptr->specific.web_service : NULL;
                        return 0;

                case 9:
                        *childptr = ( ptr->type == IDMEF_SERVICE_TYPE_SNMP ) ? ptr->specific.snmp_service : NULL;
                        return 0;

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_service_new_child(void *p, idmef_class_child_id_t child, int n, void **ret)
{
        idmef_service_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        return idmef_service_new_ident(ptr, (prelude_string_t **) ret);

                case 1:
                        return idmef_service_new_ip_version(ptr, (uint8_t **) ret);

                case 2:
                        return idmef_service_new_iana_protocol_number(ptr, (uint8_t **) ret);

                case 3:
                        return idmef_service_new_iana_protocol_name(ptr, (prelude_string_t **) ret);

                case 4:
                        return idmef_service_new_name(ptr, (prelude_string_t **) ret);

                case 5:
                        return idmef_service_new_port(ptr, (uint16_t **) ret);

                case 6:
                        return idmef_service_new_portlist(ptr, (prelude_string_t **) ret);

                case 7:
                        return idmef_service_new_protocol(ptr, (prelude_string_t **) ret);

                case 8:
                        return idmef_service_new_web_service(ptr, (idmef_web_service_t **) ret);

                case 9:
                        return idmef_service_new_snmp_service(ptr, (idmef_snmp_service_t **) ret);

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_service_destroy_child(void *p, idmef_class_child_id_t child, int n)
{
        idmef_service_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        if ( ptr->ident ) {
                                prelude_string_destroy(ptr->ident);
                                ptr->ident = NULL;
                        }

                        return 0;

                case 1:
                        ptr->ip_version_is_set = 0;
                        return 0;

                case 2:
                        ptr->iana_protocol_number_is_set = 0;
                        return 0;

                case 3:
                        if ( ptr->iana_protocol_name ) {
                                prelude_string_destroy(ptr->iana_protocol_name);
                                ptr->iana_protocol_name = NULL;
                        }

                        return 0;

                case 4:
                        if ( ptr->name ) {
                                prelude_string_destroy(ptr->name);
                                ptr->name = NULL;
                        }

                        return 0;

                case 5:
                        ptr->port_is_set = 0;
                        return 0;

                case 6:
                        if ( ptr->portlist ) {
                                prelude_string_destroy(ptr->portlist);
                                ptr->portlist = NULL;
                        }

                        return 0;

                case 7:
                        if ( ptr->protocol ) {
                                prelude_string_destroy(ptr->protocol);
                                ptr->protocol = NULL;
                        }

                        return 0;

                case 8:
                        if (  ptr->type != IDMEF_SERVICE_TYPE_WEB )
                                return 0;

                        idmef_web_service_destroy(ptr->specific.web_service);
                        ptr->specific.web_service = NULL;
                        ptr->type = 0;

                        return 0;

                case 9:
                        if (  ptr->type != IDMEF_SERVICE_TYPE_SNMP )
                                return 0;

                        idmef_snmp_service_destroy(ptr->specific.snmp_service);
                        ptr->specific.snmp_service = NULL;
                        ptr->type = 0;

                        return 0;

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

static void idmef_service_destroy_internal(idmef_service_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( ptr->ident ) {
                prelude_string_destroy(ptr->ident);
                ptr->ident = NULL;
        }

        if ( ptr->iana_protocol_name ) {
                prelude_string_destroy(ptr->iana_protocol_name);
                ptr->iana_protocol_name = NULL;
        }

        if ( ptr->name ) {
                prelude_string_destroy(ptr->name);
                ptr->name = NULL;
        }

        if ( ptr->portlist ) {
                prelude_string_destroy(ptr->portlist);
                ptr->portlist = NULL;
        }

        if ( ptr->protocol ) {
                prelude_string_destroy(ptr->protocol);
                ptr->protocol = NULL;
        }

        switch ( ptr->type ) {

                case IDMEF_SERVICE_TYPE_WEB:
                        idmef_web_service_destroy(ptr->specific.web_service);
                        ptr->specific.web_service = NULL;
                        break;

                case IDMEF_SERVICE_TYPE_SNMP:
                        idmef_snmp_service_destroy(ptr->specific.snmp_service);
                        ptr->specific.snmp_service = NULL;
                        break;

                default:
                        break;
        }


        /* free() should be done by the caller */
}

/**
 * idmef_service_destroy:
 * @ptr: pointer to a #idmef_service_t object.
 *
 * Destroy @ptr and all of it's children.
 * The objects are only destroyed if their reference count reach zero.
 */

void idmef_service_destroy(idmef_service_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( --ptr->refcount )
                return;

        idmef_service_destroy_internal(ptr);
        free(ptr);
}

/**
 * idmef_service_get_ident:
 * @ptr: pointer to a #idmef_service_t object.
 *
 * Get ident children of the #idmef_service_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_service_get_ident(idmef_service_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->ident;
}

/**
 * idmef_service_set_ident:
 * @ptr: pointer to a #idmef_service_t object.
 * @ident: pointer to a #prelude_string_t object.
 *
 * Set @ident object as a children of @ptr.
 * if @ptr already contain an @ident object, then it is destroyed,
 * and updated to point to the provided @ident object.
 */

void idmef_service_set_ident(idmef_service_t *ptr, prelude_string_t *ident)
{
        prelude_return_if_fail(ptr);

        if ( ptr->ident )
                prelude_string_destroy(ptr->ident);

        ptr->ident = ident;
}

/**
 * idmef_service_new_ident:
 * @ptr: pointer to a #idmef_service_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new ident object, children of #idmef_service_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_service_new_ident(idmef_service_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->ident ) {
                retval = prelude_string_new(&ptr->ident);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->ident;
        return 0;
}

/**
 * idmef_service_get_ip_version:
 * @ptr: pointer to a #idmef_service_t object.
 *
 * Get ip_version children of the #idmef_service_t object.
 *
 * Returns: a pointer to a uint8_t object, or NULL if the children object is not set.
 */
uint8_t *idmef_service_get_ip_version(idmef_service_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->ip_version_is_set ? &ptr->ip_version : NULL;
}

/**
 * idmef_service_set_ip_version:
 * @ptr: pointer to a #idmef_service_t object.
 * @ip_version: pointer to a #uint8_t object.
 *
 * Set @ip_version object as a children of @ptr.
 * if @ptr already contain an @ip_version object, then it is destroyed,
 * and updated to point to the provided @ip_version object.
 */

void idmef_service_set_ip_version(idmef_service_t *ptr, uint8_t ip_version)
{
        prelude_return_if_fail(ptr);
        ptr->ip_version = ip_version;
        ptr->ip_version_is_set = 1;
}


void idmef_service_unset_ip_version(idmef_service_t *ptr)
{
        prelude_return_if_fail(ptr);
        ptr->ip_version_is_set = 0;
}


/**
 * idmef_service_new_ip_version:
 * @ptr: pointer to a #idmef_service_t object.
 * @ret: pointer to an address where to store the created #uint8_t object.
 *
 * Create a new ip_version object, children of #idmef_service_t.
 * If @ptr already contain a #uint8_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_service_new_ip_version(idmef_service_t *ptr, uint8_t **ret)
{
        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));
        ptr->ip_version_is_set = 1;

        *ret = &ptr->ip_version;
        return 0;
}

/**
 * idmef_service_get_iana_protocol_number:
 * @ptr: pointer to a #idmef_service_t object.
 *
 * Get iana_protocol_number children of the #idmef_service_t object.
 *
 * Returns: a pointer to a uint8_t object, or NULL if the children object is not set.
 */
uint8_t *idmef_service_get_iana_protocol_number(idmef_service_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->iana_protocol_number_is_set ? &ptr->iana_protocol_number : NULL;
}

/**
 * idmef_service_set_iana_protocol_number:
 * @ptr: pointer to a #idmef_service_t object.
 * @iana_protocol_number: pointer to a #uint8_t object.
 *
 * Set @iana_protocol_number object as a children of @ptr.
 * if @ptr already contain an @iana_protocol_number object, then it is destroyed,
 * and updated to point to the provided @iana_protocol_number object.
 */

void idmef_service_set_iana_protocol_number(idmef_service_t *ptr, uint8_t iana_protocol_number)
{
        prelude_return_if_fail(ptr);
        ptr->iana_protocol_number = iana_protocol_number;
        ptr->iana_protocol_number_is_set = 1;
}


void idmef_service_unset_iana_protocol_number(idmef_service_t *ptr)
{
        prelude_return_if_fail(ptr);
        ptr->iana_protocol_number_is_set = 0;
}


/**
 * idmef_service_new_iana_protocol_number:
 * @ptr: pointer to a #idmef_service_t object.
 * @ret: pointer to an address where to store the created #uint8_t object.
 *
 * Create a new iana_protocol_number object, children of #idmef_service_t.
 * If @ptr already contain a #uint8_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_service_new_iana_protocol_number(idmef_service_t *ptr, uint8_t **ret)
{
        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));
        ptr->iana_protocol_number_is_set = 1;

        *ret = &ptr->iana_protocol_number;
        return 0;
}

/**
 * idmef_service_get_iana_protocol_name:
 * @ptr: pointer to a #idmef_service_t object.
 *
 * Get iana_protocol_name children of the #idmef_service_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_service_get_iana_protocol_name(idmef_service_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->iana_protocol_name;
}

/**
 * idmef_service_set_iana_protocol_name:
 * @ptr: pointer to a #idmef_service_t object.
 * @iana_protocol_name: pointer to a #prelude_string_t object.
 *
 * Set @iana_protocol_name object as a children of @ptr.
 * if @ptr already contain an @iana_protocol_name object, then it is destroyed,
 * and updated to point to the provided @iana_protocol_name object.
 */

void idmef_service_set_iana_protocol_name(idmef_service_t *ptr, prelude_string_t *iana_protocol_name)
{
        prelude_return_if_fail(ptr);

        if ( ptr->iana_protocol_name )
                prelude_string_destroy(ptr->iana_protocol_name);

        ptr->iana_protocol_name = iana_protocol_name;
}

/**
 * idmef_service_new_iana_protocol_name:
 * @ptr: pointer to a #idmef_service_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new iana_protocol_name object, children of #idmef_service_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_service_new_iana_protocol_name(idmef_service_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->iana_protocol_name ) {
                retval = prelude_string_new(&ptr->iana_protocol_name);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->iana_protocol_name;
        return 0;
}

/**
 * idmef_service_get_name:
 * @ptr: pointer to a #idmef_service_t object.
 *
 * Get name children of the #idmef_service_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_service_get_name(idmef_service_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->name;
}

/**
 * idmef_service_set_name:
 * @ptr: pointer to a #idmef_service_t object.
 * @name: pointer to a #prelude_string_t object.
 *
 * Set @name object as a children of @ptr.
 * if @ptr already contain an @name object, then it is destroyed,
 * and updated to point to the provided @name object.
 */

void idmef_service_set_name(idmef_service_t *ptr, prelude_string_t *name)
{
        prelude_return_if_fail(ptr);

        if ( ptr->name )
                prelude_string_destroy(ptr->name);

        ptr->name = name;
}

/**
 * idmef_service_new_name:
 * @ptr: pointer to a #idmef_service_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new name object, children of #idmef_service_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_service_new_name(idmef_service_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->name ) {
                retval = prelude_string_new(&ptr->name);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->name;
        return 0;
}

/**
 * idmef_service_get_port:
 * @ptr: pointer to a #idmef_service_t object.
 *
 * Get port children of the #idmef_service_t object.
 *
 * Returns: a pointer to a uint16_t object, or NULL if the children object is not set.
 */
uint16_t *idmef_service_get_port(idmef_service_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->port_is_set ? &ptr->port : NULL;
}

/**
 * idmef_service_set_port:
 * @ptr: pointer to a #idmef_service_t object.
 * @port: pointer to a #uint16_t object.
 *
 * Set @port object as a children of @ptr.
 * if @ptr already contain an @port object, then it is destroyed,
 * and updated to point to the provided @port object.
 */

void idmef_service_set_port(idmef_service_t *ptr, uint16_t port)
{
        prelude_return_if_fail(ptr);
        ptr->port = port;
        ptr->port_is_set = 1;
}


void idmef_service_unset_port(idmef_service_t *ptr)
{
        prelude_return_if_fail(ptr);
        ptr->port_is_set = 0;
}


/**
 * idmef_service_new_port:
 * @ptr: pointer to a #idmef_service_t object.
 * @ret: pointer to an address where to store the created #uint16_t object.
 *
 * Create a new port object, children of #idmef_service_t.
 * If @ptr already contain a #uint16_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_service_new_port(idmef_service_t *ptr, uint16_t **ret)
{
        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));
        ptr->port_is_set = 1;

        *ret = &ptr->port;
        return 0;
}

/**
 * idmef_service_get_portlist:
 * @ptr: pointer to a #idmef_service_t object.
 *
 * Get portlist children of the #idmef_service_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_service_get_portlist(idmef_service_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->portlist;
}

/**
 * idmef_service_set_portlist:
 * @ptr: pointer to a #idmef_service_t object.
 * @portlist: pointer to a #prelude_string_t object.
 *
 * Set @portlist object as a children of @ptr.
 * if @ptr already contain an @portlist object, then it is destroyed,
 * and updated to point to the provided @portlist object.
 */

void idmef_service_set_portlist(idmef_service_t *ptr, prelude_string_t *portlist)
{
        prelude_return_if_fail(ptr);

        if ( ptr->portlist )
                prelude_string_destroy(ptr->portlist);

        ptr->portlist = portlist;
}

/**
 * idmef_service_new_portlist:
 * @ptr: pointer to a #idmef_service_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new portlist object, children of #idmef_service_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_service_new_portlist(idmef_service_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->portlist ) {
                retval = prelude_string_new(&ptr->portlist);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->portlist;
        return 0;
}

/**
 * idmef_service_get_protocol:
 * @ptr: pointer to a #idmef_service_t object.
 *
 * Get protocol children of the #idmef_service_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_service_get_protocol(idmef_service_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->protocol;
}

/**
 * idmef_service_set_protocol:
 * @ptr: pointer to a #idmef_service_t object.
 * @protocol: pointer to a #prelude_string_t object.
 *
 * Set @protocol object as a children of @ptr.
 * if @ptr already contain an @protocol object, then it is destroyed,
 * and updated to point to the provided @protocol object.
 */

void idmef_service_set_protocol(idmef_service_t *ptr, prelude_string_t *protocol)
{
        prelude_return_if_fail(ptr);

        if ( ptr->protocol )
                prelude_string_destroy(ptr->protocol);

        ptr->protocol = protocol;
}

/**
 * idmef_service_new_protocol:
 * @ptr: pointer to a #idmef_service_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new protocol object, children of #idmef_service_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_service_new_protocol(idmef_service_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->protocol ) {
                retval = prelude_string_new(&ptr->protocol);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->protocol;
        return 0;
}

/**
 * idmef_service_get_type:
 * @ptr: pointer to a #idmef_service_t object.
 *
 * Access the type children of @ptr.
 *
 * Returns: a pointer to the #idmef_service_type_t children, or NULL if it is not set.
 */
idmef_service_type_t idmef_service_get_type(idmef_service_t *ptr)
{
        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));
        return ptr->type;
}

/**
 * idmef_service_get_web_service:
 * @ptr: pointer to a #idmef_service_t object.
 *
 * Access the web_service children of @ptr.
 *
 * Returns: a pointer to the #idmef_web_service_t children, or NULL if it is not set.
 */
idmef_web_service_t *idmef_service_get_web_service(idmef_service_t *ptr)
{
        prelude_return_val_if_fail(ptr, NULL);
        return (ptr->type == IDMEF_SERVICE_TYPE_WEB) ? ptr->specific.web_service : NULL;
}

/**
 * idmef_service_set_web_service:
 * @ptr: pointer to a #idmef_service_t object.
 * @web_service: pointer to a #idmef_web_service_t object.
 *
 * Set @web_service object as a children of @ptr.
 * if @ptr already contain a @web_service object, then it is destroyed,
 * and updated to point to the provided @web_service object.
 */
void idmef_service_set_web_service(idmef_service_t *ptr, idmef_web_service_t *web_service)
{
        prelude_return_if_fail(ptr);

        switch ( ptr->type ) {

                case IDMEF_SERVICE_TYPE_WEB:
                        idmef_web_service_destroy(ptr->specific.web_service);
                        break;

                case IDMEF_SERVICE_TYPE_SNMP:
                        idmef_snmp_service_destroy(ptr->specific.snmp_service);
                        break;

                default:
                        break;
        }

        ptr->specific.web_service = web_service;
        ptr->type = (web_service) ? IDMEF_SERVICE_TYPE_WEB : 0;
}

/**
 * idmef_service_new_web_service:
 * @ptr: pointer to a #idmef_service_t object.
 * @ret: pointer where to store the created #idmef_web_service_t object.
 *
 * Create a new idmef_web_service_t object, children of #idmef_service_t.
 * If @ptr already contain a #idmef_web_service_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_service_new_web_service(idmef_service_t *ptr, idmef_web_service_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( ptr->type ) {

                case IDMEF_SERVICE_TYPE_WEB:
                        *ret = ptr->specific.web_service;
                        return 0;

                case IDMEF_SERVICE_TYPE_SNMP:
                        idmef_snmp_service_destroy(ptr->specific.snmp_service);
                        break;

                default:
                        break;
        }

        retval = idmef_web_service_new(ret);
        if ( retval < 0 )
                return retval;

        ptr->type = IDMEF_SERVICE_TYPE_WEB;
        ptr->specific.web_service = *ret;

        return 0;
}

/**
 * idmef_service_get_snmp_service:
 * @ptr: pointer to a #idmef_service_t object.
 *
 * Access the snmp_service children of @ptr.
 *
 * Returns: a pointer to the #idmef_snmp_service_t children, or NULL if it is not set.
 */
idmef_snmp_service_t *idmef_service_get_snmp_service(idmef_service_t *ptr)
{
        prelude_return_val_if_fail(ptr, NULL);
        return (ptr->type == IDMEF_SERVICE_TYPE_SNMP) ? ptr->specific.snmp_service : NULL;
}

/**
 * idmef_service_set_snmp_service:
 * @ptr: pointer to a #idmef_service_t object.
 * @snmp_service: pointer to a #idmef_snmp_service_t object.
 *
 * Set @snmp_service object as a children of @ptr.
 * if @ptr already contain a @snmp_service object, then it is destroyed,
 * and updated to point to the provided @snmp_service object.
 */
void idmef_service_set_snmp_service(idmef_service_t *ptr, idmef_snmp_service_t *snmp_service)
{
        prelude_return_if_fail(ptr);

        switch ( ptr->type ) {

                case IDMEF_SERVICE_TYPE_WEB:
                        idmef_web_service_destroy(ptr->specific.web_service);
                        break;

                case IDMEF_SERVICE_TYPE_SNMP:
                        idmef_snmp_service_destroy(ptr->specific.snmp_service);
                        break;

                default:
                        break;
        }

        ptr->specific.snmp_service = snmp_service;
        ptr->type = (snmp_service) ? IDMEF_SERVICE_TYPE_SNMP : 0;
}

/**
 * idmef_service_new_snmp_service:
 * @ptr: pointer to a #idmef_service_t object.
 * @ret: pointer where to store the created #idmef_snmp_service_t object.
 *
 * Create a new idmef_snmp_service_t object, children of #idmef_service_t.
 * If @ptr already contain a #idmef_snmp_service_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_service_new_snmp_service(idmef_service_t *ptr, idmef_snmp_service_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( ptr->type ) {

                case IDMEF_SERVICE_TYPE_WEB:
                        idmef_web_service_destroy(ptr->specific.web_service);
                        break;

                case IDMEF_SERVICE_TYPE_SNMP:
                        *ret = ptr->specific.snmp_service;
                        return 0;

                default:
                        break;
        }

        retval = idmef_snmp_service_new(ret);
        if ( retval < 0 )
                return retval;

        ptr->type = IDMEF_SERVICE_TYPE_SNMP;
        ptr->specific.snmp_service = *ret;

        return 0;
}

/**
 * idmef_service_copy:
 * @src: Source of the copy.
 * @dst: Where to copy the object.
 *
 * Copy a new #idmef_service_t object from @src to @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_service_copy(const idmef_service_t *src, idmef_service_t *dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));
        prelude_return_val_if_fail(dst, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = 0;

        if ( dst->ident ) {
                prelude_string_destroy(dst->ident);
                dst->ident = NULL;
        }

        if ( src->ident ) {
                ret = prelude_string_clone(src->ident, &dst->ident);
                if ( ret < 0 )
                        return ret;
        }

        dst->ip_version_is_set = src->ip_version_is_set;

        dst->ip_version = src->ip_version;

        dst->iana_protocol_number_is_set = src->iana_protocol_number_is_set;

        dst->iana_protocol_number = src->iana_protocol_number;

        if ( dst->iana_protocol_name ) {
                prelude_string_destroy(dst->iana_protocol_name);
                dst->iana_protocol_name = NULL;
        }

        if ( src->iana_protocol_name ) {
                ret = prelude_string_clone(src->iana_protocol_name, &dst->iana_protocol_name);
                if ( ret < 0 )
                        return ret;
        }

        if ( dst->name ) {
                prelude_string_destroy(dst->name);
                dst->name = NULL;
        }

        if ( src->name ) {
                ret = prelude_string_clone(src->name, &dst->name);
                if ( ret < 0 )
                        return ret;
        }

        dst->port_is_set = src->port_is_set;

        dst->port = src->port;

        if ( dst->portlist ) {
                prelude_string_destroy(dst->portlist);
                dst->portlist = NULL;
        }

        if ( src->portlist ) {
                ret = prelude_string_clone(src->portlist, &dst->portlist);
                if ( ret < 0 )
                        return ret;
        }

        if ( dst->protocol ) {
                prelude_string_destroy(dst->protocol);
                dst->protocol = NULL;
        }

        if ( src->protocol ) {
                ret = prelude_string_clone(src->protocol, &dst->protocol);
                if ( ret < 0 )
                        return ret;
        }

        switch ( dst->type ) {

                case IDMEF_SERVICE_TYPE_WEB:
                        idmef_web_service_destroy(dst->specific.web_service);
                        break;

                case IDMEF_SERVICE_TYPE_SNMP:
                        idmef_snmp_service_destroy(dst->specific.snmp_service);
                        break;

                default:
                        break;
        }

        switch ( src->type ) {

                case IDMEF_SERVICE_TYPE_WEB:
                        ret = idmef_web_service_clone(src->specific.web_service, &dst->specific.web_service);
                        break;

                case IDMEF_SERVICE_TYPE_SNMP:
                        ret = idmef_snmp_service_clone(src->specific.snmp_service, &dst->specific.snmp_service);
                        break;

                default:
                        break;
        }

        if ( ret < 0 )
               return ret;

        dst->type = src->type;

        return 0;
}

/**
 * idmef_service_clone:
 * @src: Object to be cloned.
 * @dst: Address where to store the pointer to the cloned object.
 *
 * Create a copy of @src, and store it in @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_service_clone(idmef_service_t *src, idmef_service_t **dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = idmef_service_new(dst);
        if ( ret < 0 )
                return ret;

        return idmef_service_copy(src, *dst);
}

/**
 * idmef_service_compare:
 * @obj1: Object to compare with @obj2.
 * @obj2: Object to compare with @obj1.
 *
 * Compare @obj1 with @obj2.
 *
 * Returns: 0 on match, a negative value on comparison failure.
 */
int idmef_service_compare(const idmef_service_t *obj1, const idmef_service_t *obj2)
{
        int ret = 0;

        if ( obj1 == NULL && obj2 == NULL )
                return 0;

        else if ( obj1 == NULL || obj2 == NULL )
                return -1;

        ret = prelude_string_compare(obj1->ident, obj2->ident);
        if ( ret != 0 )
                return ret;

        if ( obj1->ip_version_is_set != obj2->ip_version_is_set )
                return -1;

        if ( obj1->ip_version_is_set && obj1->ip_version != obj2->ip_version )
                return -1;

        if ( obj1->iana_protocol_number_is_set != obj2->iana_protocol_number_is_set )
                return -1;

        if ( obj1->iana_protocol_number_is_set && obj1->iana_protocol_number != obj2->iana_protocol_number )
                return -1;

        ret = prelude_string_compare(obj1->iana_protocol_name, obj2->iana_protocol_name);
        if ( ret != 0 )
                return ret;

        ret = prelude_string_compare(obj1->name, obj2->name);
        if ( ret != 0 )
                return ret;

        if ( obj1->port_is_set != obj2->port_is_set )
                return -1;

        if ( obj1->port_is_set && obj1->port != obj2->port )
                return -1;

        ret = prelude_string_compare(obj1->portlist, obj2->portlist);
        if ( ret != 0 )
                return ret;

        ret = prelude_string_compare(obj1->protocol, obj2->protocol);
        if ( ret != 0 )
                return ret;

        if ( obj1->type != obj2->type )
                return -1;

        switch ( obj1->type ) {

                case IDMEF_SERVICE_TYPE_WEB:
                        ret = idmef_web_service_compare(obj1->specific.web_service, obj2->specific.web_service);
                        break;

                case IDMEF_SERVICE_TYPE_SNMP:
                        ret = idmef_snmp_service_compare(obj1->specific.snmp_service, obj2->specific.snmp_service);
                        break;

                default:
                        break;
        }

        return ret;
}

/**
 * idmef_node_new:
 * @ret: Pointer where to store the created #idmef_node_t object.
 *
 * Create a new #idmef_node_t object.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_node_new(idmef_node_t **ret)
{
        *ret = calloc(1, sizeof(**ret));
        if ( ! *ret )
                return prelude_error_from_errno(errno);

        (*ret)->_idmef_object_id = IDMEF_CLASS_ID_NODE;

        (*ret)->refcount = 1;

        prelude_list_init(&(*ret)->address_list);


        return 0;

}

/**
 * idmef_node_ref:
 * @node: pointer to a #idmef_node_t object.
 *
 * Increase @node reference count, so that it can be referenced
 * multiple time.
 *
 * Returns: a pointer to @node.
 */
idmef_node_t *idmef_node_ref(idmef_node_t *node)
{
        prelude_return_val_if_fail(node, NULL);
        node->refcount++;

        return node;
}

int _idmef_node_get_child(void *p, idmef_class_child_id_t child, void **childptr)
{
        idmef_node_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));
        *childptr = NULL;

        switch ( child ) {

                case 0:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->ident, TRUE);
                case 1:
                       return idmef_value_new_enum_from_numeric((idmef_value_t **) childptr,
                                                                IDMEF_CLASS_ID_NODE_CATEGORY, ptr->category);

                case 2:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->location, TRUE);
                case 3:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->name, TRUE);
                case 4:
                        *childptr = &ptr->address_list;
                        return 0;

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_node_new_child(void *p, idmef_class_child_id_t child, int n, void **ret)
{
        idmef_node_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        return idmef_node_new_ident(ptr, (prelude_string_t **) ret);

                case 1:
                        return idmef_node_new_category(ptr, (idmef_node_category_t **) ret);

                case 2:
                        return idmef_node_new_location(ptr, (prelude_string_t **) ret);

                case 3:
                        return idmef_node_new_name(ptr, (prelude_string_t **) ret);

                case 4: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n == IDMEF_LIST_APPEND || n == IDMEF_LIST_PREPEND )
                               return idmef_node_new_address(ptr, (idmef_address_t **) ret, n);

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->address_list, tmp) {
                                       if ( i++ == n ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->address_list, tmp) {
                                       if ( i++ == pos ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }

                        return idmef_node_new_address(ptr, (idmef_address_t **) ret, n);
                }

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_node_destroy_child(void *p, idmef_class_child_id_t child, int n)
{
        idmef_node_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        if ( ptr->ident ) {
                                prelude_string_destroy(ptr->ident);
                                ptr->ident = NULL;
                        }

                        return 0;

                case 1:
                        ptr->category = 0;
                        return 0;

                case 2:
                        if ( ptr->location ) {
                                prelude_string_destroy(ptr->location);
                                ptr->location = NULL;
                        }

                        return 0;

                case 3:
                        if ( ptr->name ) {
                                prelude_string_destroy(ptr->name);
                                ptr->name = NULL;
                        }

                        return 0;

                case 4: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->address_list, tmp) {
                                       if ( i++ == n ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               idmef_address_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->address_list, tmp) {
                                       if ( i++ == pos ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               idmef_address_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }
                }

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

static void idmef_node_destroy_internal(idmef_node_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( ptr->ident ) {
                prelude_string_destroy(ptr->ident);
                ptr->ident = NULL;
        }

        if ( ptr->location ) {
                prelude_string_destroy(ptr->location);
                ptr->location = NULL;
        }

        if ( ptr->name ) {
                prelude_string_destroy(ptr->name);
                ptr->name = NULL;
        }

        {
                prelude_list_t *n, *tmp;
                idmef_address_t *entry;

                prelude_list_for_each_safe(&ptr->address_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        prelude_list_del_init(tmp);
                        idmef_address_destroy(entry);
                }
        }


        /* free() should be done by the caller */
}

/**
 * idmef_node_destroy:
 * @ptr: pointer to a #idmef_node_t object.
 *
 * Destroy @ptr and all of it's children.
 * The objects are only destroyed if their reference count reach zero.
 */

void idmef_node_destroy(idmef_node_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( --ptr->refcount )
                return;

        idmef_node_destroy_internal(ptr);
        free(ptr);
}

/**
 * idmef_node_get_ident:
 * @ptr: pointer to a #idmef_node_t object.
 *
 * Get ident children of the #idmef_node_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_node_get_ident(idmef_node_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->ident;
}

/**
 * idmef_node_set_ident:
 * @ptr: pointer to a #idmef_node_t object.
 * @ident: pointer to a #prelude_string_t object.
 *
 * Set @ident object as a children of @ptr.
 * if @ptr already contain an @ident object, then it is destroyed,
 * and updated to point to the provided @ident object.
 */

void idmef_node_set_ident(idmef_node_t *ptr, prelude_string_t *ident)
{
        prelude_return_if_fail(ptr);

        if ( ptr->ident )
                prelude_string_destroy(ptr->ident);

        ptr->ident = ident;
}

/**
 * idmef_node_new_ident:
 * @ptr: pointer to a #idmef_node_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new ident object, children of #idmef_node_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_node_new_ident(idmef_node_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->ident ) {
                retval = prelude_string_new(&ptr->ident);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->ident;
        return 0;
}

/**
 * idmef_node_get_category:
 * @ptr: pointer to a #idmef_node_t object.
 *
 * Get category children of the #idmef_node_t object.
 *
 * Returns: a pointer to a idmef_node_category_t object, or NULL if the children object is not set.
 */
idmef_node_category_t idmef_node_get_category(idmef_node_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->category;
}

/**
 * idmef_node_set_category:
 * @ptr: pointer to a #idmef_node_t object.
 * @category: pointer to a #idmef_node_category_t object.
 *
 * Set @category object as a children of @ptr.
 * if @ptr already contain an @category object, then it is destroyed,
 * and updated to point to the provided @category object.
 */

void idmef_node_set_category(idmef_node_t *ptr, idmef_node_category_t category)
{
        prelude_return_if_fail(ptr);
        ptr->category = category;
}

/**
 * idmef_node_new_category:
 * @ptr: pointer to a #idmef_node_t object.
 * @ret: pointer to an address where to store the created #idmef_node_category_t object.
 *
 * Create a new category object, children of #idmef_node_t.
 * If @ptr already contain a #idmef_node_category_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_node_new_category(idmef_node_t *ptr, idmef_node_category_t **ret)
{
        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        *ret = &ptr->category;
        return 0;
}

/**
 * idmef_node_get_location:
 * @ptr: pointer to a #idmef_node_t object.
 *
 * Get location children of the #idmef_node_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_node_get_location(idmef_node_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->location;
}

/**
 * idmef_node_set_location:
 * @ptr: pointer to a #idmef_node_t object.
 * @location: pointer to a #prelude_string_t object.
 *
 * Set @location object as a children of @ptr.
 * if @ptr already contain an @location object, then it is destroyed,
 * and updated to point to the provided @location object.
 */

void idmef_node_set_location(idmef_node_t *ptr, prelude_string_t *location)
{
        prelude_return_if_fail(ptr);

        if ( ptr->location )
                prelude_string_destroy(ptr->location);

        ptr->location = location;
}

/**
 * idmef_node_new_location:
 * @ptr: pointer to a #idmef_node_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new location object, children of #idmef_node_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_node_new_location(idmef_node_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->location ) {
                retval = prelude_string_new(&ptr->location);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->location;
        return 0;
}

/**
 * idmef_node_get_name:
 * @ptr: pointer to a #idmef_node_t object.
 *
 * Get name children of the #idmef_node_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_node_get_name(idmef_node_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->name;
}

/**
 * idmef_node_set_name:
 * @ptr: pointer to a #idmef_node_t object.
 * @name: pointer to a #prelude_string_t object.
 *
 * Set @name object as a children of @ptr.
 * if @ptr already contain an @name object, then it is destroyed,
 * and updated to point to the provided @name object.
 */

void idmef_node_set_name(idmef_node_t *ptr, prelude_string_t *name)
{
        prelude_return_if_fail(ptr);

        if ( ptr->name )
                prelude_string_destroy(ptr->name);

        ptr->name = name;
}

/**
 * idmef_node_new_name:
 * @ptr: pointer to a #idmef_node_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new name object, children of #idmef_node_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_node_new_name(idmef_node_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->name ) {
                retval = prelude_string_new(&ptr->name);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->name;
        return 0;
}

/**
 * idmef_node_get_next_address:
 * @node: pointer to a #idmef_node_t object.
 * @address_cur: pointer to a #idmef_address_t object.
 *
 * Get the next #idmef_address_t object listed in @ptr.
 * When iterating over the idmef_address_t object listed in @ptr,
 * @object should be set to the latest returned #idmef_address_t object.
 *
 * Returns: the next #idmef_address_t in the list.
 */
idmef_address_t *idmef_node_get_next_address(idmef_node_t *node, idmef_address_t *address_cur)
{
        prelude_list_t *tmp = (address_cur) ? &((prelude_linked_object_t *) address_cur)->_list : NULL;

        prelude_return_val_if_fail(node, NULL);

        prelude_list_for_each_continue(&node->address_list, tmp)
                return prelude_linked_object_get_object(tmp);

        return NULL;
}


/**
 * idmef_node_set_address:
 * @ptr: pointer to a #idmef_node_t object.
 * @object: pointer to a #idmef_address_t object.
 * @pos: Position in the list.
 *
 * Add @object to position @pos of @ptr list of #idmef_address_t object.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 */
void idmef_node_set_address(idmef_node_t *ptr, idmef_address_t *object, int pos)
{
        prelude_return_if_fail(ptr);
        prelude_return_if_fail(object);

        if ( ! prelude_list_is_empty(&((prelude_linked_object_t *) object)->_list) )
                prelude_list_del_init(&((prelude_linked_object_t *) object)->_list);

        list_insert(&ptr->address_list, &((prelude_linked_object_t *) object)->_list, pos);
}


/**
 * idmef_node_new_address:
 * @ptr: pointer to a #idmef_node_t object.
 * @ret: pointer to an address where to store the created #idmef_address_t object.
 * @pos: position in the list.
 *
 * Create a new #idmef_address_t children of @ptr, and add it to position @pos of
 * @ptr list of #idmef_address_t object. The created #idmef_address_t object is
 * stored in @ret.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_node_new_address(idmef_node_t *ptr, idmef_address_t **ret, int pos)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        retval = idmef_address_new(ret);
        if ( retval < 0 )
                return retval;

        list_insert(&ptr->address_list, &((prelude_linked_object_t *)(*ret))->_list, pos);

        return 0;
}


/**
 * idmef_node_copy:
 * @src: Source of the copy.
 * @dst: Where to copy the object.
 *
 * Copy a new #idmef_node_t object from @src to @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_node_copy(const idmef_node_t *src, idmef_node_t *dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));
        prelude_return_val_if_fail(dst, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = 0;

        if ( dst->ident ) {
                prelude_string_destroy(dst->ident);
                dst->ident = NULL;
        }

        if ( src->ident ) {
                ret = prelude_string_clone(src->ident, &dst->ident);
                if ( ret < 0 )
                        return ret;
        }

        dst->category = src->category;

        if ( dst->location ) {
                prelude_string_destroy(dst->location);
                dst->location = NULL;
        }

        if ( src->location ) {
                ret = prelude_string_clone(src->location, &dst->location);
                if ( ret < 0 )
                        return ret;
        }

        if ( dst->name ) {
                prelude_string_destroy(dst->name);
                dst->name = NULL;
        }

        if ( src->name ) {
                ret = prelude_string_clone(src->name, &dst->name);
                if ( ret < 0 )
                        return ret;
        }

        {
                prelude_list_t *n, *tmp;
                idmef_address_t *entry, *new;

                prelude_list_for_each_safe(&dst->address_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        idmef_address_destroy(entry);
                }

                prelude_list_for_each_safe(&src->address_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        idmef_address_clone(entry, &new);
                        prelude_list_add_tail(&dst->address_list, &((prelude_linked_object_t *) new)->_list);
                }
        }

        return 0;
}

/**
 * idmef_node_clone:
 * @src: Object to be cloned.
 * @dst: Address where to store the pointer to the cloned object.
 *
 * Create a copy of @src, and store it in @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_node_clone(idmef_node_t *src, idmef_node_t **dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = idmef_node_new(dst);
        if ( ret < 0 )
                return ret;

        return idmef_node_copy(src, *dst);
}

/**
 * idmef_node_compare:
 * @obj1: Object to compare with @obj2.
 * @obj2: Object to compare with @obj1.
 *
 * Compare @obj1 with @obj2.
 *
 * Returns: 0 on match, a negative value on comparison failure.
 */
int idmef_node_compare(const idmef_node_t *obj1, const idmef_node_t *obj2)
{
        int ret = 0;

        if ( obj1 == NULL && obj2 == NULL )
                return 0;

        else if ( obj1 == NULL || obj2 == NULL )
                return -1;

        ret = prelude_string_compare(obj1->ident, obj2->ident);
        if ( ret != 0 )
                return ret;

        if ( obj1->category != obj2->category )
                return -1;

        ret = prelude_string_compare(obj1->location, obj2->location);
        if ( ret != 0 )
                return ret;

        ret = prelude_string_compare(obj1->name, obj2->name);
        if ( ret != 0 )
                return ret;

        {
                prelude_list_t *tmp1, *tmp2;
                idmef_address_t *entry1, *entry2;

                tmp1 = tmp2 = NULL;
                do {
                        entry1 = entry2 = NULL;

                        prelude_list_for_each_continue(&obj1->address_list, tmp1) {
                                entry1 = prelude_linked_object_get_object(tmp1);
                                break;
                        }

                        prelude_list_for_each_continue(&obj2->address_list, tmp2) {
                                entry2 = prelude_linked_object_get_object(tmp2);
                                break;
                        }

                        ret = idmef_address_compare(entry1, entry2);
                        if ( ret != 0 )
                                return ret;

                } while ( entry1 && entry2 );
        }

        return ret;
}

/**
 * idmef_source_new:
 * @ret: Pointer where to store the created #idmef_source_t object.
 *
 * Create a new #idmef_source_t object.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_source_new(idmef_source_t **ret)
{
        *ret = calloc(1, sizeof(**ret));
        if ( ! *ret )
                return prelude_error_from_errno(errno);

        (*ret)->_idmef_object_id = IDMEF_CLASS_ID_SOURCE;

        prelude_list_init(&((prelude_linked_object_t *) (*ret))->_list);

        (*ret)->refcount = 1;

        return 0;

}

/**
 * idmef_source_ref:
 * @source: pointer to a #idmef_source_t object.
 *
 * Increase @source reference count, so that it can be referenced
 * multiple time.
 *
 * Returns: a pointer to @source.
 */
idmef_source_t *idmef_source_ref(idmef_source_t *source)
{
        prelude_return_val_if_fail(source, NULL);
        source->refcount++;

        return source;
}

int _idmef_source_get_child(void *p, idmef_class_child_id_t child, void **childptr)
{
        idmef_source_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));
        *childptr = NULL;

        switch ( child ) {

                case 0:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->ident, TRUE);
                case 1:
                       return idmef_value_new_enum_from_numeric((idmef_value_t **) childptr,
                                                                IDMEF_CLASS_ID_SOURCE_SPOOFED, ptr->spoofed);

                case 2:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->interface, TRUE);
                case 3:
                        *childptr = ptr->node;
                        return 0;

                case 4:
                        *childptr = ptr->user;
                        return 0;

                case 5:
                        *childptr = ptr->process;
                        return 0;

                case 6:
                        *childptr = ptr->service;
                        return 0;

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_source_new_child(void *p, idmef_class_child_id_t child, int n, void **ret)
{
        idmef_source_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        return idmef_source_new_ident(ptr, (prelude_string_t **) ret);

                case 1:
                        return idmef_source_new_spoofed(ptr, (idmef_source_spoofed_t **) ret);

                case 2:
                        return idmef_source_new_interface(ptr, (prelude_string_t **) ret);

                case 3:
                        return idmef_source_new_node(ptr, (idmef_node_t **) ret);

                case 4:
                        return idmef_source_new_user(ptr, (idmef_user_t **) ret);

                case 5:
                        return idmef_source_new_process(ptr, (idmef_process_t **) ret);

                case 6:
                        return idmef_source_new_service(ptr, (idmef_service_t **) ret);

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_source_destroy_child(void *p, idmef_class_child_id_t child, int n)
{
        idmef_source_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        if ( ptr->ident ) {
                                prelude_string_destroy(ptr->ident);
                                ptr->ident = NULL;
                        }

                        return 0;

                case 1:
                        ptr->spoofed = 0;
                        return 0;

                case 2:
                        if ( ptr->interface ) {
                                prelude_string_destroy(ptr->interface);
                                ptr->interface = NULL;
                        }

                        return 0;

                case 3:
                        if ( ptr->node ) {
                                idmef_node_destroy(ptr->node);
                                ptr->node = NULL;
                        }

                        return 0;

                case 4:
                        if ( ptr->user ) {
                                idmef_user_destroy(ptr->user);
                                ptr->user = NULL;
                        }

                        return 0;

                case 5:
                        if ( ptr->process ) {
                                idmef_process_destroy(ptr->process);
                                ptr->process = NULL;
                        }

                        return 0;

                case 6:
                        if ( ptr->service ) {
                                idmef_service_destroy(ptr->service);
                                ptr->service = NULL;
                        }

                        return 0;

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

static void idmef_source_destroy_internal(idmef_source_t *ptr)
{
        prelude_return_if_fail(ptr);

       if ( ! prelude_list_is_empty(&((prelude_linked_object_t *)ptr)->_list) )
               prelude_list_del_init(&((prelude_linked_object_t *)ptr)->_list);
    
        if ( ptr->ident ) {
                prelude_string_destroy(ptr->ident);
                ptr->ident = NULL;
        }

        if ( ptr->interface ) {
                prelude_string_destroy(ptr->interface);
                ptr->interface = NULL;
        }

        if ( ptr->node ) {
                idmef_node_destroy(ptr->node);
                ptr->node = NULL;
        }

        if ( ptr->user ) {
                idmef_user_destroy(ptr->user);
                ptr->user = NULL;
        }

        if ( ptr->process ) {
                idmef_process_destroy(ptr->process);
                ptr->process = NULL;
        }

        if ( ptr->service ) {
                idmef_service_destroy(ptr->service);
                ptr->service = NULL;
        }


        /* free() should be done by the caller */
}

/**
 * idmef_source_destroy:
 * @ptr: pointer to a #idmef_source_t object.
 *
 * Destroy @ptr and all of it's children.
 * The objects are only destroyed if their reference count reach zero.
 */

void idmef_source_destroy(idmef_source_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( --ptr->refcount )
                return;

        idmef_source_destroy_internal(ptr);
        free(ptr);
}

/**
 * idmef_source_get_ident:
 * @ptr: pointer to a #idmef_source_t object.
 *
 * Get ident children of the #idmef_source_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_source_get_ident(idmef_source_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->ident;
}

/**
 * idmef_source_set_ident:
 * @ptr: pointer to a #idmef_source_t object.
 * @ident: pointer to a #prelude_string_t object.
 *
 * Set @ident object as a children of @ptr.
 * if @ptr already contain an @ident object, then it is destroyed,
 * and updated to point to the provided @ident object.
 */

void idmef_source_set_ident(idmef_source_t *ptr, prelude_string_t *ident)
{
        prelude_return_if_fail(ptr);

        if ( ptr->ident )
                prelude_string_destroy(ptr->ident);

        ptr->ident = ident;
}

/**
 * idmef_source_new_ident:
 * @ptr: pointer to a #idmef_source_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new ident object, children of #idmef_source_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_source_new_ident(idmef_source_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->ident ) {
                retval = prelude_string_new(&ptr->ident);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->ident;
        return 0;
}

/**
 * idmef_source_get_spoofed:
 * @ptr: pointer to a #idmef_source_t object.
 *
 * Get spoofed children of the #idmef_source_t object.
 *
 * Returns: a pointer to a idmef_source_spoofed_t object, or NULL if the children object is not set.
 */
idmef_source_spoofed_t idmef_source_get_spoofed(idmef_source_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->spoofed;
}

/**
 * idmef_source_set_spoofed:
 * @ptr: pointer to a #idmef_source_t object.
 * @spoofed: pointer to a #idmef_source_spoofed_t object.
 *
 * Set @spoofed object as a children of @ptr.
 * if @ptr already contain an @spoofed object, then it is destroyed,
 * and updated to point to the provided @spoofed object.
 */

void idmef_source_set_spoofed(idmef_source_t *ptr, idmef_source_spoofed_t spoofed)
{
        prelude_return_if_fail(ptr);
        ptr->spoofed = spoofed;
}

/**
 * idmef_source_new_spoofed:
 * @ptr: pointer to a #idmef_source_t object.
 * @ret: pointer to an address where to store the created #idmef_source_spoofed_t object.
 *
 * Create a new spoofed object, children of #idmef_source_t.
 * If @ptr already contain a #idmef_source_spoofed_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_source_new_spoofed(idmef_source_t *ptr, idmef_source_spoofed_t **ret)
{
        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        *ret = &ptr->spoofed;
        return 0;
}

/**
 * idmef_source_get_interface:
 * @ptr: pointer to a #idmef_source_t object.
 *
 * Get interface children of the #idmef_source_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_source_get_interface(idmef_source_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->interface;
}

/**
 * idmef_source_set_interface:
 * @ptr: pointer to a #idmef_source_t object.
 * @interface: pointer to a #prelude_string_t object.
 *
 * Set @interface object as a children of @ptr.
 * if @ptr already contain an @interface object, then it is destroyed,
 * and updated to point to the provided @interface object.
 */

void idmef_source_set_interface(idmef_source_t *ptr, prelude_string_t *interface)
{
        prelude_return_if_fail(ptr);

        if ( ptr->interface )
                prelude_string_destroy(ptr->interface);

        ptr->interface = interface;
}

/**
 * idmef_source_new_interface:
 * @ptr: pointer to a #idmef_source_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new interface object, children of #idmef_source_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_source_new_interface(idmef_source_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->interface ) {
                retval = prelude_string_new(&ptr->interface);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->interface;
        return 0;
}

/**
 * idmef_source_get_node:
 * @ptr: pointer to a #idmef_source_t object.
 *
 * Get node children of the #idmef_source_t object.
 *
 * Returns: a pointer to a idmef_node_t object, or NULL if the children object is not set.
 */
idmef_node_t *idmef_source_get_node(idmef_source_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->node;
}

/**
 * idmef_source_set_node:
 * @ptr: pointer to a #idmef_source_t object.
 * @node: pointer to a #idmef_node_t object.
 *
 * Set @node object as a children of @ptr.
 * if @ptr already contain an @node object, then it is destroyed,
 * and updated to point to the provided @node object.
 */

void idmef_source_set_node(idmef_source_t *ptr, idmef_node_t *node)
{
        prelude_return_if_fail(ptr);

        if ( ptr->node )
                idmef_node_destroy(ptr->node);

        ptr->node = node;
}

/**
 * idmef_source_new_node:
 * @ptr: pointer to a #idmef_source_t object.
 * @ret: pointer to an address where to store the created #idmef_node_t object.
 *
 * Create a new node object, children of #idmef_source_t.
 * If @ptr already contain a #idmef_node_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_source_new_node(idmef_source_t *ptr, idmef_node_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->node ) {
                retval = idmef_node_new(&ptr->node);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->node;
        return 0;
}

/**
 * idmef_source_get_user:
 * @ptr: pointer to a #idmef_source_t object.
 *
 * Get user children of the #idmef_source_t object.
 *
 * Returns: a pointer to a idmef_user_t object, or NULL if the children object is not set.
 */
idmef_user_t *idmef_source_get_user(idmef_source_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->user;
}

/**
 * idmef_source_set_user:
 * @ptr: pointer to a #idmef_source_t object.
 * @user: pointer to a #idmef_user_t object.
 *
 * Set @user object as a children of @ptr.
 * if @ptr already contain an @user object, then it is destroyed,
 * and updated to point to the provided @user object.
 */

void idmef_source_set_user(idmef_source_t *ptr, idmef_user_t *user)
{
        prelude_return_if_fail(ptr);

        if ( ptr->user )
                idmef_user_destroy(ptr->user);

        ptr->user = user;
}

/**
 * idmef_source_new_user:
 * @ptr: pointer to a #idmef_source_t object.
 * @ret: pointer to an address where to store the created #idmef_user_t object.
 *
 * Create a new user object, children of #idmef_source_t.
 * If @ptr already contain a #idmef_user_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_source_new_user(idmef_source_t *ptr, idmef_user_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->user ) {
                retval = idmef_user_new(&ptr->user);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->user;
        return 0;
}

/**
 * idmef_source_get_process:
 * @ptr: pointer to a #idmef_source_t object.
 *
 * Get process children of the #idmef_source_t object.
 *
 * Returns: a pointer to a idmef_process_t object, or NULL if the children object is not set.
 */
idmef_process_t *idmef_source_get_process(idmef_source_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->process;
}

/**
 * idmef_source_set_process:
 * @ptr: pointer to a #idmef_source_t object.
 * @process: pointer to a #idmef_process_t object.
 *
 * Set @process object as a children of @ptr.
 * if @ptr already contain an @process object, then it is destroyed,
 * and updated to point to the provided @process object.
 */

void idmef_source_set_process(idmef_source_t *ptr, idmef_process_t *process)
{
        prelude_return_if_fail(ptr);

        if ( ptr->process )
                idmef_process_destroy(ptr->process);

        ptr->process = process;
}

/**
 * idmef_source_new_process:
 * @ptr: pointer to a #idmef_source_t object.
 * @ret: pointer to an address where to store the created #idmef_process_t object.
 *
 * Create a new process object, children of #idmef_source_t.
 * If @ptr already contain a #idmef_process_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_source_new_process(idmef_source_t *ptr, idmef_process_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->process ) {
                retval = idmef_process_new(&ptr->process);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->process;
        return 0;
}

/**
 * idmef_source_get_service:
 * @ptr: pointer to a #idmef_source_t object.
 *
 * Get service children of the #idmef_source_t object.
 *
 * Returns: a pointer to a idmef_service_t object, or NULL if the children object is not set.
 */
idmef_service_t *idmef_source_get_service(idmef_source_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->service;
}

/**
 * idmef_source_set_service:
 * @ptr: pointer to a #idmef_source_t object.
 * @service: pointer to a #idmef_service_t object.
 *
 * Set @service object as a children of @ptr.
 * if @ptr already contain an @service object, then it is destroyed,
 * and updated to point to the provided @service object.
 */

void idmef_source_set_service(idmef_source_t *ptr, idmef_service_t *service)
{
        prelude_return_if_fail(ptr);

        if ( ptr->service )
                idmef_service_destroy(ptr->service);

        ptr->service = service;
}

/**
 * idmef_source_new_service:
 * @ptr: pointer to a #idmef_source_t object.
 * @ret: pointer to an address where to store the created #idmef_service_t object.
 *
 * Create a new service object, children of #idmef_source_t.
 * If @ptr already contain a #idmef_service_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_source_new_service(idmef_source_t *ptr, idmef_service_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->service ) {
                retval = idmef_service_new(&ptr->service);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->service;
        return 0;
}

/**
 * idmef_source_copy:
 * @src: Source of the copy.
 * @dst: Where to copy the object.
 *
 * Copy a new #idmef_source_t object from @src to @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_source_copy(const idmef_source_t *src, idmef_source_t *dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));
        prelude_return_val_if_fail(dst, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = 0;

        if ( dst->ident ) {
                prelude_string_destroy(dst->ident);
                dst->ident = NULL;
        }

        if ( src->ident ) {
                ret = prelude_string_clone(src->ident, &dst->ident);
                if ( ret < 0 )
                        return ret;
        }

        dst->spoofed = src->spoofed;

        if ( dst->interface ) {
                prelude_string_destroy(dst->interface);
                dst->interface = NULL;
        }

        if ( src->interface ) {
                ret = prelude_string_clone(src->interface, &dst->interface);
                if ( ret < 0 )
                        return ret;
        }

        if ( dst->node ) {
                idmef_node_destroy(dst->node);
                dst->node = NULL;
        }

        if ( src->node ) {
                ret = idmef_node_clone(src->node, &dst->node);
                if ( ret < 0 )
                        return ret;
        }

        if ( dst->user ) {
                idmef_user_destroy(dst->user);
                dst->user = NULL;
        }

        if ( src->user ) {
                ret = idmef_user_clone(src->user, &dst->user);
                if ( ret < 0 )
                        return ret;
        }

        if ( dst->process ) {
                idmef_process_destroy(dst->process);
                dst->process = NULL;
        }

        if ( src->process ) {
                ret = idmef_process_clone(src->process, &dst->process);
                if ( ret < 0 )
                        return ret;
        }

        if ( dst->service ) {
                idmef_service_destroy(dst->service);
                dst->service = NULL;
        }

        if ( src->service ) {
                ret = idmef_service_clone(src->service, &dst->service);
                if ( ret < 0 )
                        return ret;
        }

        return 0;
}

/**
 * idmef_source_clone:
 * @src: Object to be cloned.
 * @dst: Address where to store the pointer to the cloned object.
 *
 * Create a copy of @src, and store it in @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_source_clone(idmef_source_t *src, idmef_source_t **dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = idmef_source_new(dst);
        if ( ret < 0 )
                return ret;

        return idmef_source_copy(src, *dst);
}

/**
 * idmef_source_compare:
 * @obj1: Object to compare with @obj2.
 * @obj2: Object to compare with @obj1.
 *
 * Compare @obj1 with @obj2.
 *
 * Returns: 0 on match, a negative value on comparison failure.
 */
int idmef_source_compare(const idmef_source_t *obj1, const idmef_source_t *obj2)
{
        int ret = 0;

        if ( obj1 == NULL && obj2 == NULL )
                return 0;

        else if ( obj1 == NULL || obj2 == NULL )
                return -1;

        ret = prelude_string_compare(obj1->ident, obj2->ident);
        if ( ret != 0 )
                return ret;

        if ( obj1->spoofed != obj2->spoofed )
                return -1;

        ret = prelude_string_compare(obj1->interface, obj2->interface);
        if ( ret != 0 )
                return ret;

        ret = idmef_node_compare(obj1->node, obj2->node);
        if ( ret != 0 )
                return ret;

        ret = idmef_user_compare(obj1->user, obj2->user);
        if ( ret != 0 )
                return ret;

        ret = idmef_process_compare(obj1->process, obj2->process);
        if ( ret != 0 )
                return ret;

        ret = idmef_service_compare(obj1->service, obj2->service);
        if ( ret != 0 )
                return ret;

        return ret;
}

/**
 * idmef_file_access_new:
 * @ret: Pointer where to store the created #idmef_file_access_t object.
 *
 * Create a new #idmef_file_access_t object.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_file_access_new(idmef_file_access_t **ret)
{
        *ret = calloc(1, sizeof(**ret));
        if ( ! *ret )
                return prelude_error_from_errno(errno);

        (*ret)->_idmef_object_id = IDMEF_CLASS_ID_FILE_ACCESS;

        prelude_list_init(&((prelude_linked_object_t *) (*ret))->_list);

        (*ret)->refcount = 1;

        prelude_list_init(&(*ret)->permission_list);


        {
                int retval = idmef_user_id_new(&(*ret)->user_id);

                if ( retval < 0 ) {
                        idmef_file_access_destroy(*ret);
                        *ret = NULL;
                        return retval;
                }
        }

        return 0;

}

/**
 * idmef_file_access_ref:
 * @file_access: pointer to a #idmef_file_access_t object.
 *
 * Increase @file_access reference count, so that it can be referenced
 * multiple time.
 *
 * Returns: a pointer to @file_access.
 */
idmef_file_access_t *idmef_file_access_ref(idmef_file_access_t *file_access)
{
        prelude_return_val_if_fail(file_access, NULL);
        file_access->refcount++;

        return file_access;
}

int _idmef_file_access_get_child(void *p, idmef_class_child_id_t child, void **childptr)
{
        idmef_file_access_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));
        *childptr = NULL;

        switch ( child ) {

                case 0:
                        *childptr = ptr->user_id;
                        return 0;

                case 1:
                        *childptr = &ptr->permission_list;
                        return 0;

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_file_access_new_child(void *p, idmef_class_child_id_t child, int n, void **ret)
{
        idmef_file_access_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        return idmef_file_access_new_user_id(ptr, (idmef_user_id_t **) ret);

                case 1: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n == IDMEF_LIST_APPEND || n == IDMEF_LIST_PREPEND )
                               return idmef_file_access_new_permission(ptr, (prelude_string_t **) ret, n);

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->permission_list, tmp) {
                                       if ( i++ == n ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->permission_list, tmp) {
                                       if ( i++ == pos ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }

                        return idmef_file_access_new_permission(ptr, (prelude_string_t **) ret, n);
                }

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_file_access_destroy_child(void *p, idmef_class_child_id_t child, int n)
{
        idmef_file_access_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        if ( ptr->user_id ) {
                                idmef_user_id_destroy(ptr->user_id);
                                ptr->user_id = NULL;
                        }

                        return 0;

                case 1: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->permission_list, tmp) {
                                       if ( i++ == n ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               prelude_string_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->permission_list, tmp) {
                                       if ( i++ == pos ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               prelude_string_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }
                }

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

static void idmef_file_access_destroy_internal(idmef_file_access_t *ptr)
{
        prelude_return_if_fail(ptr);

       if ( ! prelude_list_is_empty(&((prelude_linked_object_t *)ptr)->_list) )
               prelude_list_del_init(&((prelude_linked_object_t *)ptr)->_list);
    
        if ( ptr->user_id ) {
                idmef_user_id_destroy(ptr->user_id);
                ptr->user_id = NULL;
        }

        {
                prelude_list_t *n, *tmp;
                prelude_string_t *entry;

                prelude_list_for_each_safe(&ptr->permission_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        prelude_list_del_init(tmp);
                        prelude_string_destroy(entry);
                }
        }


        /* free() should be done by the caller */
}

/**
 * idmef_file_access_destroy:
 * @ptr: pointer to a #idmef_file_access_t object.
 *
 * Destroy @ptr and all of it's children.
 * The objects are only destroyed if their reference count reach zero.
 */

void idmef_file_access_destroy(idmef_file_access_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( --ptr->refcount )
                return;

        idmef_file_access_destroy_internal(ptr);
        free(ptr);
}

/**
 * idmef_file_access_get_user_id:
 * @ptr: pointer to a #idmef_file_access_t object.
 *
 * Get user_id children of the #idmef_file_access_t object.
 *
 * Returns: a pointer to a idmef_user_id_t object, or NULL if the children object is not set.
 */
idmef_user_id_t *idmef_file_access_get_user_id(idmef_file_access_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->user_id;
}

/**
 * idmef_file_access_set_user_id:
 * @ptr: pointer to a #idmef_file_access_t object.
 * @user_id: pointer to a #idmef_user_id_t object.
 *
 * Set @user_id object as a children of @ptr.
 * if @ptr already contain an @user_id object, then it is destroyed,
 * and updated to point to the provided @user_id object.
 */

void idmef_file_access_set_user_id(idmef_file_access_t *ptr, idmef_user_id_t *user_id)
{
        prelude_return_if_fail(ptr);

        if ( ptr->user_id )
                idmef_user_id_destroy(ptr->user_id);

        ptr->user_id = user_id;
}

/**
 * idmef_file_access_new_user_id:
 * @ptr: pointer to a #idmef_file_access_t object.
 * @ret: pointer to an address where to store the created #idmef_user_id_t object.
 *
 * Create a new user_id object, children of #idmef_file_access_t.
 * If @ptr already contain a #idmef_user_id_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_file_access_new_user_id(idmef_file_access_t *ptr, idmef_user_id_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->user_id ) {
                retval = idmef_user_id_new(&ptr->user_id);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->user_id;
        return 0;
}

/**
 * idmef_file_access_get_next_permission:
 * @file_access: pointer to a #idmef_file_access_t object.
 * @prelude_string_cur: pointer to a #prelude_string_t object.
 *
 * Get the next #prelude_string_t object listed in @ptr.
 * When iterating over the prelude_string_t object listed in @ptr,
 * @object should be set to the latest returned #prelude_string_t object.
 *
 * Returns: the next #prelude_string_t in the list.
 */
prelude_string_t *idmef_file_access_get_next_permission(idmef_file_access_t *file_access, prelude_string_t *prelude_string_cur)
{
        prelude_list_t *tmp = (prelude_string_cur) ? &((prelude_linked_object_t *) prelude_string_cur)->_list : NULL;

        prelude_return_val_if_fail(file_access, NULL);

        prelude_list_for_each_continue(&file_access->permission_list, tmp)
                return prelude_linked_object_get_object(tmp);

        return NULL;
}


/**
 * idmef_file_access_set_permission:
 * @ptr: pointer to a #idmef_file_access_t object.
 * @object: pointer to a #prelude_string_t object.
 * @pos: Position in the list.
 *
 * Add @object to position @pos of @ptr list of #prelude_string_t object.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 */
void idmef_file_access_set_permission(idmef_file_access_t *ptr, prelude_string_t *object, int pos)
{
        prelude_return_if_fail(ptr);
        prelude_return_if_fail(object);

        if ( ! prelude_list_is_empty(&((prelude_linked_object_t *) object)->_list) )
                prelude_list_del_init(&((prelude_linked_object_t *) object)->_list);

        list_insert(&ptr->permission_list, &((prelude_linked_object_t *) object)->_list, pos);
}


/**
 * idmef_file_access_new_permission:
 * @ptr: pointer to a #idmef_file_access_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 * @pos: position in the list.
 *
 * Create a new #prelude_string_t children of @ptr, and add it to position @pos of
 * @ptr list of #prelude_string_t object. The created #prelude_string_t object is
 * stored in @ret.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_file_access_new_permission(idmef_file_access_t *ptr, prelude_string_t **ret, int pos)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        retval = prelude_string_new(ret);
        if ( retval < 0 )
                return retval;

        list_insert(&ptr->permission_list, &((prelude_linked_object_t *)(*ret))->_list, pos);

        return 0;
}


/**
 * idmef_file_access_copy:
 * @src: Source of the copy.
 * @dst: Where to copy the object.
 *
 * Copy a new #idmef_file_access_t object from @src to @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_file_access_copy(const idmef_file_access_t *src, idmef_file_access_t *dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));
        prelude_return_val_if_fail(dst, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = 0;

        if ( src->user_id ) {
                ret = idmef_user_id_copy(src->user_id, dst->user_id);
                if ( ret < 0 )
                        return ret;
        }

        {
                prelude_list_t *n, *tmp;
                prelude_string_t *entry, *new;

                prelude_list_for_each_safe(&dst->permission_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        prelude_string_destroy(entry);
                }

                prelude_list_for_each_safe(&src->permission_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        prelude_string_clone(entry, &new);
                        prelude_list_add_tail(&dst->permission_list, &((prelude_linked_object_t *) new)->_list);
                }
        }

        return 0;
}

/**
 * idmef_file_access_clone:
 * @src: Object to be cloned.
 * @dst: Address where to store the pointer to the cloned object.
 *
 * Create a copy of @src, and store it in @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_file_access_clone(idmef_file_access_t *src, idmef_file_access_t **dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = idmef_file_access_new(dst);
        if ( ret < 0 )
                return ret;

        return idmef_file_access_copy(src, *dst);
}

/**
 * idmef_file_access_compare:
 * @obj1: Object to compare with @obj2.
 * @obj2: Object to compare with @obj1.
 *
 * Compare @obj1 with @obj2.
 *
 * Returns: 0 on match, a negative value on comparison failure.
 */
int idmef_file_access_compare(const idmef_file_access_t *obj1, const idmef_file_access_t *obj2)
{
        int ret = 0;

        if ( obj1 == NULL && obj2 == NULL )
                return 0;

        else if ( obj1 == NULL || obj2 == NULL )
                return -1;

        ret = idmef_user_id_compare(obj1->user_id, obj2->user_id);
        if ( ret != 0 )
                return ret;

        {
                prelude_list_t *tmp1, *tmp2;
                prelude_string_t *entry1, *entry2;

                tmp1 = tmp2 = NULL;
                do {
                        entry1 = entry2 = NULL;

                        prelude_list_for_each_continue(&obj1->permission_list, tmp1) {
                                entry1 = prelude_linked_object_get_object(tmp1);
                                break;
                        }

                        prelude_list_for_each_continue(&obj2->permission_list, tmp2) {
                                entry2 = prelude_linked_object_get_object(tmp2);
                                break;
                        }

                        ret = prelude_string_compare(entry1, entry2);
                        if ( ret != 0 )
                                return ret;

                } while ( entry1 && entry2 );
        }

        return ret;
}

/**
 * idmef_inode_new:
 * @ret: Pointer where to store the created #idmef_inode_t object.
 *
 * Create a new #idmef_inode_t object.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_inode_new(idmef_inode_t **ret)
{
        *ret = calloc(1, sizeof(**ret));
        if ( ! *ret )
                return prelude_error_from_errno(errno);

        (*ret)->_idmef_object_id = IDMEF_CLASS_ID_INODE;

        (*ret)->refcount = 1;

        return 0;

}

/**
 * idmef_inode_ref:
 * @inode: pointer to a #idmef_inode_t object.
 *
 * Increase @inode reference count, so that it can be referenced
 * multiple time.
 *
 * Returns: a pointer to @inode.
 */
idmef_inode_t *idmef_inode_ref(idmef_inode_t *inode)
{
        prelude_return_val_if_fail(inode, NULL);
        inode->refcount++;

        return inode;
}

int _idmef_inode_get_child(void *p, idmef_class_child_id_t child, void **childptr)
{
        idmef_inode_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));
        *childptr = NULL;

        switch ( child ) {

                case 0:
                       return get_value_from_time((idmef_value_t **) childptr,  ptr->change_time, TRUE);
                case 1:
                       return (ptr->number_is_set) ? idmef_value_new_uint32((idmef_value_t **) childptr, ptr->number) : 0;

                case 2:
                       return (ptr->major_device_is_set) ? idmef_value_new_uint32((idmef_value_t **) childptr, ptr->major_device) : 0;

                case 3:
                       return (ptr->minor_device_is_set) ? idmef_value_new_uint32((idmef_value_t **) childptr, ptr->minor_device) : 0;

                case 4:
                       return (ptr->c_major_device_is_set) ? idmef_value_new_uint32((idmef_value_t **) childptr, ptr->c_major_device) : 0;

                case 5:
                       return (ptr->c_minor_device_is_set) ? idmef_value_new_uint32((idmef_value_t **) childptr, ptr->c_minor_device) : 0;

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_inode_new_child(void *p, idmef_class_child_id_t child, int n, void **ret)
{
        idmef_inode_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        return idmef_inode_new_change_time(ptr, (idmef_time_t **) ret);

                case 1:
                        return idmef_inode_new_number(ptr, (uint32_t **) ret);

                case 2:
                        return idmef_inode_new_major_device(ptr, (uint32_t **) ret);

                case 3:
                        return idmef_inode_new_minor_device(ptr, (uint32_t **) ret);

                case 4:
                        return idmef_inode_new_c_major_device(ptr, (uint32_t **) ret);

                case 5:
                        return idmef_inode_new_c_minor_device(ptr, (uint32_t **) ret);

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_inode_destroy_child(void *p, idmef_class_child_id_t child, int n)
{
        idmef_inode_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        if ( ptr->change_time ) {
                                idmef_time_destroy(ptr->change_time);
                                ptr->change_time = NULL;
                        }

                        return 0;

                case 1:
                        ptr->number_is_set = 0;
                        return 0;

                case 2:
                        ptr->major_device_is_set = 0;
                        return 0;

                case 3:
                        ptr->minor_device_is_set = 0;
                        return 0;

                case 4:
                        ptr->c_major_device_is_set = 0;
                        return 0;

                case 5:
                        ptr->c_minor_device_is_set = 0;
                        return 0;

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

static void idmef_inode_destroy_internal(idmef_inode_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( ptr->change_time ) {
                idmef_time_destroy(ptr->change_time);
                ptr->change_time = NULL;
        }


        /* free() should be done by the caller */
}

/**
 * idmef_inode_destroy:
 * @ptr: pointer to a #idmef_inode_t object.
 *
 * Destroy @ptr and all of it's children.
 * The objects are only destroyed if their reference count reach zero.
 */

void idmef_inode_destroy(idmef_inode_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( --ptr->refcount )
                return;

        idmef_inode_destroy_internal(ptr);
        free(ptr);
}

/**
 * idmef_inode_get_change_time:
 * @ptr: pointer to a #idmef_inode_t object.
 *
 * Get change_time children of the #idmef_inode_t object.
 *
 * Returns: a pointer to a idmef_time_t object, or NULL if the children object is not set.
 */
idmef_time_t *idmef_inode_get_change_time(idmef_inode_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->change_time;
}

/**
 * idmef_inode_set_change_time:
 * @ptr: pointer to a #idmef_inode_t object.
 * @change_time: pointer to a #idmef_time_t object.
 *
 * Set @change_time object as a children of @ptr.
 * if @ptr already contain an @change_time object, then it is destroyed,
 * and updated to point to the provided @change_time object.
 */

void idmef_inode_set_change_time(idmef_inode_t *ptr, idmef_time_t *change_time)
{
        prelude_return_if_fail(ptr);

        if ( ptr->change_time )
                idmef_time_destroy(ptr->change_time);

        ptr->change_time = change_time;
}

/**
 * idmef_inode_new_change_time:
 * @ptr: pointer to a #idmef_inode_t object.
 * @ret: pointer to an address where to store the created #idmef_time_t object.
 *
 * Create a new change_time object, children of #idmef_inode_t.
 * If @ptr already contain a #idmef_time_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_inode_new_change_time(idmef_inode_t *ptr, idmef_time_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->change_time ) {
                retval = idmef_time_new(&ptr->change_time);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->change_time;
        return 0;
}

/**
 * idmef_inode_get_number:
 * @ptr: pointer to a #idmef_inode_t object.
 *
 * Get number children of the #idmef_inode_t object.
 *
 * Returns: a pointer to a uint32_t object, or NULL if the children object is not set.
 */
uint32_t *idmef_inode_get_number(idmef_inode_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->number_is_set ? &ptr->number : NULL;
}

/**
 * idmef_inode_set_number:
 * @ptr: pointer to a #idmef_inode_t object.
 * @number: pointer to a #uint32_t object.
 *
 * Set @number object as a children of @ptr.
 * if @ptr already contain an @number object, then it is destroyed,
 * and updated to point to the provided @number object.
 */

void idmef_inode_set_number(idmef_inode_t *ptr, uint32_t number)
{
        prelude_return_if_fail(ptr);
        ptr->number = number;
        ptr->number_is_set = 1;
}


void idmef_inode_unset_number(idmef_inode_t *ptr)
{
        prelude_return_if_fail(ptr);
        ptr->number_is_set = 0;
}


/**
 * idmef_inode_new_number:
 * @ptr: pointer to a #idmef_inode_t object.
 * @ret: pointer to an address where to store the created #uint32_t object.
 *
 * Create a new number object, children of #idmef_inode_t.
 * If @ptr already contain a #uint32_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_inode_new_number(idmef_inode_t *ptr, uint32_t **ret)
{
        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));
        ptr->number_is_set = 1;

        *ret = &ptr->number;
        return 0;
}

/**
 * idmef_inode_get_major_device:
 * @ptr: pointer to a #idmef_inode_t object.
 *
 * Get major_device children of the #idmef_inode_t object.
 *
 * Returns: a pointer to a uint32_t object, or NULL if the children object is not set.
 */
uint32_t *idmef_inode_get_major_device(idmef_inode_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->major_device_is_set ? &ptr->major_device : NULL;
}

/**
 * idmef_inode_set_major_device:
 * @ptr: pointer to a #idmef_inode_t object.
 * @major_device: pointer to a #uint32_t object.
 *
 * Set @major_device object as a children of @ptr.
 * if @ptr already contain an @major_device object, then it is destroyed,
 * and updated to point to the provided @major_device object.
 */

void idmef_inode_set_major_device(idmef_inode_t *ptr, uint32_t major_device)
{
        prelude_return_if_fail(ptr);
        ptr->major_device = major_device;
        ptr->major_device_is_set = 1;
}


void idmef_inode_unset_major_device(idmef_inode_t *ptr)
{
        prelude_return_if_fail(ptr);
        ptr->major_device_is_set = 0;
}


/**
 * idmef_inode_new_major_device:
 * @ptr: pointer to a #idmef_inode_t object.
 * @ret: pointer to an address where to store the created #uint32_t object.
 *
 * Create a new major_device object, children of #idmef_inode_t.
 * If @ptr already contain a #uint32_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_inode_new_major_device(idmef_inode_t *ptr, uint32_t **ret)
{
        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));
        ptr->major_device_is_set = 1;

        *ret = &ptr->major_device;
        return 0;
}

/**
 * idmef_inode_get_minor_device:
 * @ptr: pointer to a #idmef_inode_t object.
 *
 * Get minor_device children of the #idmef_inode_t object.
 *
 * Returns: a pointer to a uint32_t object, or NULL if the children object is not set.
 */
uint32_t *idmef_inode_get_minor_device(idmef_inode_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->minor_device_is_set ? &ptr->minor_device : NULL;
}

/**
 * idmef_inode_set_minor_device:
 * @ptr: pointer to a #idmef_inode_t object.
 * @minor_device: pointer to a #uint32_t object.
 *
 * Set @minor_device object as a children of @ptr.
 * if @ptr already contain an @minor_device object, then it is destroyed,
 * and updated to point to the provided @minor_device object.
 */

void idmef_inode_set_minor_device(idmef_inode_t *ptr, uint32_t minor_device)
{
        prelude_return_if_fail(ptr);
        ptr->minor_device = minor_device;
        ptr->minor_device_is_set = 1;
}


void idmef_inode_unset_minor_device(idmef_inode_t *ptr)
{
        prelude_return_if_fail(ptr);
        ptr->minor_device_is_set = 0;
}


/**
 * idmef_inode_new_minor_device:
 * @ptr: pointer to a #idmef_inode_t object.
 * @ret: pointer to an address where to store the created #uint32_t object.
 *
 * Create a new minor_device object, children of #idmef_inode_t.
 * If @ptr already contain a #uint32_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_inode_new_minor_device(idmef_inode_t *ptr, uint32_t **ret)
{
        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));
        ptr->minor_device_is_set = 1;

        *ret = &ptr->minor_device;
        return 0;
}

/**
 * idmef_inode_get_c_major_device:
 * @ptr: pointer to a #idmef_inode_t object.
 *
 * Get c_major_device children of the #idmef_inode_t object.
 *
 * Returns: a pointer to a uint32_t object, or NULL if the children object is not set.
 */
uint32_t *idmef_inode_get_c_major_device(idmef_inode_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->c_major_device_is_set ? &ptr->c_major_device : NULL;
}

/**
 * idmef_inode_set_c_major_device:
 * @ptr: pointer to a #idmef_inode_t object.
 * @c_major_device: pointer to a #uint32_t object.
 *
 * Set @c_major_device object as a children of @ptr.
 * if @ptr already contain an @c_major_device object, then it is destroyed,
 * and updated to point to the provided @c_major_device object.
 */

void idmef_inode_set_c_major_device(idmef_inode_t *ptr, uint32_t c_major_device)
{
        prelude_return_if_fail(ptr);
        ptr->c_major_device = c_major_device;
        ptr->c_major_device_is_set = 1;
}


void idmef_inode_unset_c_major_device(idmef_inode_t *ptr)
{
        prelude_return_if_fail(ptr);
        ptr->c_major_device_is_set = 0;
}


/**
 * idmef_inode_new_c_major_device:
 * @ptr: pointer to a #idmef_inode_t object.
 * @ret: pointer to an address where to store the created #uint32_t object.
 *
 * Create a new c_major_device object, children of #idmef_inode_t.
 * If @ptr already contain a #uint32_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_inode_new_c_major_device(idmef_inode_t *ptr, uint32_t **ret)
{
        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));
        ptr->c_major_device_is_set = 1;

        *ret = &ptr->c_major_device;
        return 0;
}

/**
 * idmef_inode_get_c_minor_device:
 * @ptr: pointer to a #idmef_inode_t object.
 *
 * Get c_minor_device children of the #idmef_inode_t object.
 *
 * Returns: a pointer to a uint32_t object, or NULL if the children object is not set.
 */
uint32_t *idmef_inode_get_c_minor_device(idmef_inode_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->c_minor_device_is_set ? &ptr->c_minor_device : NULL;
}

/**
 * idmef_inode_set_c_minor_device:
 * @ptr: pointer to a #idmef_inode_t object.
 * @c_minor_device: pointer to a #uint32_t object.
 *
 * Set @c_minor_device object as a children of @ptr.
 * if @ptr already contain an @c_minor_device object, then it is destroyed,
 * and updated to point to the provided @c_minor_device object.
 */

void idmef_inode_set_c_minor_device(idmef_inode_t *ptr, uint32_t c_minor_device)
{
        prelude_return_if_fail(ptr);
        ptr->c_minor_device = c_minor_device;
        ptr->c_minor_device_is_set = 1;
}


void idmef_inode_unset_c_minor_device(idmef_inode_t *ptr)
{
        prelude_return_if_fail(ptr);
        ptr->c_minor_device_is_set = 0;
}


/**
 * idmef_inode_new_c_minor_device:
 * @ptr: pointer to a #idmef_inode_t object.
 * @ret: pointer to an address where to store the created #uint32_t object.
 *
 * Create a new c_minor_device object, children of #idmef_inode_t.
 * If @ptr already contain a #uint32_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_inode_new_c_minor_device(idmef_inode_t *ptr, uint32_t **ret)
{
        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));
        ptr->c_minor_device_is_set = 1;

        *ret = &ptr->c_minor_device;
        return 0;
}

/**
 * idmef_inode_copy:
 * @src: Source of the copy.
 * @dst: Where to copy the object.
 *
 * Copy a new #idmef_inode_t object from @src to @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_inode_copy(const idmef_inode_t *src, idmef_inode_t *dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));
        prelude_return_val_if_fail(dst, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = 0;

        if ( dst->change_time ) {
                idmef_time_destroy(dst->change_time);
                dst->change_time = NULL;
        }

        if ( src->change_time ) {
                ret = idmef_time_clone(src->change_time, &dst->change_time);
                if ( ret < 0 )
                        return ret;
        }

        dst->number_is_set = src->number_is_set;

        dst->number = src->number;

        dst->major_device_is_set = src->major_device_is_set;

        dst->major_device = src->major_device;

        dst->minor_device_is_set = src->minor_device_is_set;

        dst->minor_device = src->minor_device;

        dst->c_major_device_is_set = src->c_major_device_is_set;

        dst->c_major_device = src->c_major_device;

        dst->c_minor_device_is_set = src->c_minor_device_is_set;

        dst->c_minor_device = src->c_minor_device;

        return 0;
}

/**
 * idmef_inode_clone:
 * @src: Object to be cloned.
 * @dst: Address where to store the pointer to the cloned object.
 *
 * Create a copy of @src, and store it in @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_inode_clone(idmef_inode_t *src, idmef_inode_t **dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = idmef_inode_new(dst);
        if ( ret < 0 )
                return ret;

        return idmef_inode_copy(src, *dst);
}

/**
 * idmef_inode_compare:
 * @obj1: Object to compare with @obj2.
 * @obj2: Object to compare with @obj1.
 *
 * Compare @obj1 with @obj2.
 *
 * Returns: 0 on match, a negative value on comparison failure.
 */
int idmef_inode_compare(const idmef_inode_t *obj1, const idmef_inode_t *obj2)
{
        int ret = 0;

        if ( obj1 == NULL && obj2 == NULL )
                return 0;

        else if ( obj1 == NULL || obj2 == NULL )
                return -1;

        ret = idmef_time_compare(obj1->change_time, obj2->change_time);
        if ( ret != 0 )
                return ret;

        if ( obj1->number_is_set != obj2->number_is_set )
                return -1;

        if ( obj1->number_is_set && obj1->number != obj2->number )
                return -1;

        if ( obj1->major_device_is_set != obj2->major_device_is_set )
                return -1;

        if ( obj1->major_device_is_set && obj1->major_device != obj2->major_device )
                return -1;

        if ( obj1->minor_device_is_set != obj2->minor_device_is_set )
                return -1;

        if ( obj1->minor_device_is_set && obj1->minor_device != obj2->minor_device )
                return -1;

        if ( obj1->c_major_device_is_set != obj2->c_major_device_is_set )
                return -1;

        if ( obj1->c_major_device_is_set && obj1->c_major_device != obj2->c_major_device )
                return -1;

        if ( obj1->c_minor_device_is_set != obj2->c_minor_device_is_set )
                return -1;

        if ( obj1->c_minor_device_is_set && obj1->c_minor_device != obj2->c_minor_device )
                return -1;

        return ret;
}

/**
 * idmef_checksum_new:
 * @ret: Pointer where to store the created #idmef_checksum_t object.
 *
 * Create a new #idmef_checksum_t object.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_checksum_new(idmef_checksum_t **ret)
{
        *ret = calloc(1, sizeof(**ret));
        if ( ! *ret )
                return prelude_error_from_errno(errno);

        (*ret)->_idmef_object_id = IDMEF_CLASS_ID_CHECKSUM;

        prelude_list_init(&((prelude_linked_object_t *) (*ret))->_list);

        (*ret)->refcount = 1;

        {
                int retval = prelude_string_new(&(*ret)->value);

                if ( retval < 0 ) {
                        idmef_checksum_destroy(*ret);
                        *ret = NULL;
                        return retval;
                }
        }

        return 0;

}

/**
 * idmef_checksum_ref:
 * @checksum: pointer to a #idmef_checksum_t object.
 *
 * Increase @checksum reference count, so that it can be referenced
 * multiple time.
 *
 * Returns: a pointer to @checksum.
 */
idmef_checksum_t *idmef_checksum_ref(idmef_checksum_t *checksum)
{
        prelude_return_val_if_fail(checksum, NULL);
        checksum->refcount++;

        return checksum;
}

int _idmef_checksum_get_child(void *p, idmef_class_child_id_t child, void **childptr)
{
        idmef_checksum_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));
        *childptr = NULL;

        switch ( child ) {

                case 0:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->value, TRUE);
                case 1:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->key, TRUE);
                case 2:
                       return idmef_value_new_enum_from_numeric((idmef_value_t **) childptr,
                                                                IDMEF_CLASS_ID_CHECKSUM_ALGORITHM, ptr->algorithm);

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_checksum_new_child(void *p, idmef_class_child_id_t child, int n, void **ret)
{
        idmef_checksum_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        return idmef_checksum_new_value(ptr, (prelude_string_t **) ret);

                case 1:
                        return idmef_checksum_new_key(ptr, (prelude_string_t **) ret);

                case 2:
                        return idmef_checksum_new_algorithm(ptr, (idmef_checksum_algorithm_t **) ret);

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_checksum_destroy_child(void *p, idmef_class_child_id_t child, int n)
{
        idmef_checksum_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        if ( ptr->value ) {
                                prelude_string_destroy(ptr->value);
                                ptr->value = NULL;
                        }

                        return 0;

                case 1:
                        if ( ptr->key ) {
                                prelude_string_destroy(ptr->key);
                                ptr->key = NULL;
                        }

                        return 0;

                case 2:
                        ptr->algorithm = 0;
                        return 0;

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

static void idmef_checksum_destroy_internal(idmef_checksum_t *ptr)
{
        prelude_return_if_fail(ptr);

       if ( ! prelude_list_is_empty(&((prelude_linked_object_t *)ptr)->_list) )
               prelude_list_del_init(&((prelude_linked_object_t *)ptr)->_list);
    
        if ( ptr->value ) {
                prelude_string_destroy(ptr->value);
                ptr->value = NULL;
        }

        if ( ptr->key ) {
                prelude_string_destroy(ptr->key);
                ptr->key = NULL;
        }


        /* free() should be done by the caller */
}

/**
 * idmef_checksum_destroy:
 * @ptr: pointer to a #idmef_checksum_t object.
 *
 * Destroy @ptr and all of it's children.
 * The objects are only destroyed if their reference count reach zero.
 */

void idmef_checksum_destroy(idmef_checksum_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( --ptr->refcount )
                return;

        idmef_checksum_destroy_internal(ptr);
        free(ptr);
}

/**
 * idmef_checksum_get_value:
 * @ptr: pointer to a #idmef_checksum_t object.
 *
 * Get value children of the #idmef_checksum_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_checksum_get_value(idmef_checksum_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->value;
}

/**
 * idmef_checksum_set_value:
 * @ptr: pointer to a #idmef_checksum_t object.
 * @value: pointer to a #prelude_string_t object.
 *
 * Set @value object as a children of @ptr.
 * if @ptr already contain an @value object, then it is destroyed,
 * and updated to point to the provided @value object.
 */

void idmef_checksum_set_value(idmef_checksum_t *ptr, prelude_string_t *value)
{
        prelude_return_if_fail(ptr);

        if ( ptr->value )
                prelude_string_destroy(ptr->value);

        ptr->value = value;
}

/**
 * idmef_checksum_new_value:
 * @ptr: pointer to a #idmef_checksum_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new value object, children of #idmef_checksum_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_checksum_new_value(idmef_checksum_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->value ) {
                retval = prelude_string_new(&ptr->value);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->value;
        return 0;
}

/**
 * idmef_checksum_get_key:
 * @ptr: pointer to a #idmef_checksum_t object.
 *
 * Get key children of the #idmef_checksum_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_checksum_get_key(idmef_checksum_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->key;
}

/**
 * idmef_checksum_set_key:
 * @ptr: pointer to a #idmef_checksum_t object.
 * @key: pointer to a #prelude_string_t object.
 *
 * Set @key object as a children of @ptr.
 * if @ptr already contain an @key object, then it is destroyed,
 * and updated to point to the provided @key object.
 */

void idmef_checksum_set_key(idmef_checksum_t *ptr, prelude_string_t *key)
{
        prelude_return_if_fail(ptr);

        if ( ptr->key )
                prelude_string_destroy(ptr->key);

        ptr->key = key;
}

/**
 * idmef_checksum_new_key:
 * @ptr: pointer to a #idmef_checksum_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new key object, children of #idmef_checksum_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_checksum_new_key(idmef_checksum_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->key ) {
                retval = prelude_string_new(&ptr->key);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->key;
        return 0;
}

/**
 * idmef_checksum_get_algorithm:
 * @ptr: pointer to a #idmef_checksum_t object.
 *
 * Get algorithm children of the #idmef_checksum_t object.
 *
 * Returns: a pointer to a idmef_checksum_algorithm_t object, or NULL if the children object is not set.
 */
idmef_checksum_algorithm_t idmef_checksum_get_algorithm(idmef_checksum_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->algorithm;
}

/**
 * idmef_checksum_set_algorithm:
 * @ptr: pointer to a #idmef_checksum_t object.
 * @algorithm: pointer to a #idmef_checksum_algorithm_t object.
 *
 * Set @algorithm object as a children of @ptr.
 * if @ptr already contain an @algorithm object, then it is destroyed,
 * and updated to point to the provided @algorithm object.
 */

void idmef_checksum_set_algorithm(idmef_checksum_t *ptr, idmef_checksum_algorithm_t algorithm)
{
        prelude_return_if_fail(ptr);
        ptr->algorithm = algorithm;
}

/**
 * idmef_checksum_new_algorithm:
 * @ptr: pointer to a #idmef_checksum_t object.
 * @ret: pointer to an address where to store the created #idmef_checksum_algorithm_t object.
 *
 * Create a new algorithm object, children of #idmef_checksum_t.
 * If @ptr already contain a #idmef_checksum_algorithm_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_checksum_new_algorithm(idmef_checksum_t *ptr, idmef_checksum_algorithm_t **ret)
{
        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        *ret = &ptr->algorithm;
        return 0;
}

/**
 * idmef_checksum_copy:
 * @src: Source of the copy.
 * @dst: Where to copy the object.
 *
 * Copy a new #idmef_checksum_t object from @src to @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_checksum_copy(const idmef_checksum_t *src, idmef_checksum_t *dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));
        prelude_return_val_if_fail(dst, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = 0;

        if ( src->value ) {
                ret = prelude_string_copy(src->value, dst->value);
                if ( ret < 0 )
                        return ret;
        }

        if ( dst->key ) {
                prelude_string_destroy(dst->key);
                dst->key = NULL;
        }

        if ( src->key ) {
                ret = prelude_string_clone(src->key, &dst->key);
                if ( ret < 0 )
                        return ret;
        }

        dst->algorithm = src->algorithm;

        return 0;
}

/**
 * idmef_checksum_clone:
 * @src: Object to be cloned.
 * @dst: Address where to store the pointer to the cloned object.
 *
 * Create a copy of @src, and store it in @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_checksum_clone(idmef_checksum_t *src, idmef_checksum_t **dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = idmef_checksum_new(dst);
        if ( ret < 0 )
                return ret;

        return idmef_checksum_copy(src, *dst);
}

/**
 * idmef_checksum_compare:
 * @obj1: Object to compare with @obj2.
 * @obj2: Object to compare with @obj1.
 *
 * Compare @obj1 with @obj2.
 *
 * Returns: 0 on match, a negative value on comparison failure.
 */
int idmef_checksum_compare(const idmef_checksum_t *obj1, const idmef_checksum_t *obj2)
{
        int ret = 0;

        if ( obj1 == NULL && obj2 == NULL )
                return 0;

        else if ( obj1 == NULL || obj2 == NULL )
                return -1;

        ret = prelude_string_compare(obj1->value, obj2->value);
        if ( ret != 0 )
                return ret;

        ret = prelude_string_compare(obj1->key, obj2->key);
        if ( ret != 0 )
                return ret;

        if ( obj1->algorithm != obj2->algorithm )
                return -1;

        return ret;
}

/**
 * idmef_file_new:
 * @ret: Pointer where to store the created #idmef_file_t object.
 *
 * Create a new #idmef_file_t object.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_file_new(idmef_file_t **ret)
{
        *ret = calloc(1, sizeof(**ret));
        if ( ! *ret )
                return prelude_error_from_errno(errno);

        (*ret)->_idmef_object_id = IDMEF_CLASS_ID_FILE;

        prelude_list_init(&((prelude_linked_object_t *) (*ret))->_list);

        (*ret)->refcount = 1;

        prelude_list_init(&(*ret)->file_access_list);


        prelude_list_init(&(*ret)->linkage_list);


        prelude_list_init(&(*ret)->checksum_list);


        {
                int retval = prelude_string_new(&(*ret)->name);

                if ( retval < 0 ) {
                        idmef_file_destroy(*ret);
                        *ret = NULL;
                        return retval;
                }
        }

        {
                int retval = prelude_string_new(&(*ret)->path);

                if ( retval < 0 ) {
                        idmef_file_destroy(*ret);
                        *ret = NULL;
                        return retval;
                }
        }

        return 0;

}

/**
 * idmef_file_ref:
 * @file: pointer to a #idmef_file_t object.
 *
 * Increase @file reference count, so that it can be referenced
 * multiple time.
 *
 * Returns: a pointer to @file.
 */
idmef_file_t *idmef_file_ref(idmef_file_t *file)
{
        prelude_return_val_if_fail(file, NULL);
        file->refcount++;

        return file;
}

int _idmef_file_get_child(void *p, idmef_class_child_id_t child, void **childptr)
{
        idmef_file_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));
        *childptr = NULL;

        switch ( child ) {

                case 0:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->ident, TRUE);
                case 1:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->name, TRUE);
                case 2:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->path, TRUE);
                case 3:
                       return get_value_from_time((idmef_value_t **) childptr,  ptr->create_time, TRUE);
                case 4:
                       return get_value_from_time((idmef_value_t **) childptr,  ptr->modify_time, TRUE);
                case 5:
                       return get_value_from_time((idmef_value_t **) childptr,  ptr->access_time, TRUE);
                case 6:
                       return (ptr->data_size_is_set) ? idmef_value_new_uint64((idmef_value_t **) childptr, ptr->data_size) : 0;

                case 7:
                       return (ptr->disk_size_is_set) ? idmef_value_new_uint64((idmef_value_t **) childptr, ptr->disk_size) : 0;

                case 8:
                        *childptr = &ptr->file_access_list;
                        return 0;

                case 9:
                        *childptr = &ptr->linkage_list;
                        return 0;

                case 10:
                        *childptr = ptr->inode;
                        return 0;

                case 11:
                        *childptr = &ptr->checksum_list;
                        return 0;

                case 12:
                       return idmef_value_new_enum_from_numeric((idmef_value_t **) childptr,
                                                                IDMEF_CLASS_ID_FILE_CATEGORY, ptr->category);

                case 13:
                       if ( ! ptr->fstype_is_set )
                               return 0;
                       return idmef_value_new_enum_from_numeric((idmef_value_t **) childptr,
                                                                IDMEF_CLASS_ID_FILE_FSTYPE, ptr->fstype);

                case 14:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->file_type, TRUE);
                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_file_new_child(void *p, idmef_class_child_id_t child, int n, void **ret)
{
        idmef_file_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        return idmef_file_new_ident(ptr, (prelude_string_t **) ret);

                case 1:
                        return idmef_file_new_name(ptr, (prelude_string_t **) ret);

                case 2:
                        return idmef_file_new_path(ptr, (prelude_string_t **) ret);

                case 3:
                        return idmef_file_new_create_time(ptr, (idmef_time_t **) ret);

                case 4:
                        return idmef_file_new_modify_time(ptr, (idmef_time_t **) ret);

                case 5:
                        return idmef_file_new_access_time(ptr, (idmef_time_t **) ret);

                case 6:
                        return idmef_file_new_data_size(ptr, (uint64_t **) ret);

                case 7:
                        return idmef_file_new_disk_size(ptr, (uint64_t **) ret);

                case 8: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n == IDMEF_LIST_APPEND || n == IDMEF_LIST_PREPEND )
                               return idmef_file_new_file_access(ptr, (idmef_file_access_t **) ret, n);

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->file_access_list, tmp) {
                                       if ( i++ == n ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->file_access_list, tmp) {
                                       if ( i++ == pos ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }

                        return idmef_file_new_file_access(ptr, (idmef_file_access_t **) ret, n);
                }

                case 9: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n == IDMEF_LIST_APPEND || n == IDMEF_LIST_PREPEND )
                               return idmef_file_new_linkage(ptr, (idmef_linkage_t **) ret, n);

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->linkage_list, tmp) {
                                       if ( i++ == n ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->linkage_list, tmp) {
                                       if ( i++ == pos ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }

                        return idmef_file_new_linkage(ptr, (idmef_linkage_t **) ret, n);
                }

                case 10:
                        return idmef_file_new_inode(ptr, (idmef_inode_t **) ret);

                case 11: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n == IDMEF_LIST_APPEND || n == IDMEF_LIST_PREPEND )
                               return idmef_file_new_checksum(ptr, (idmef_checksum_t **) ret, n);

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->checksum_list, tmp) {
                                       if ( i++ == n ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->checksum_list, tmp) {
                                       if ( i++ == pos ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }

                        return idmef_file_new_checksum(ptr, (idmef_checksum_t **) ret, n);
                }

                case 12:
                        return idmef_file_new_category(ptr, (idmef_file_category_t **) ret);

                case 13:
                        return idmef_file_new_fstype(ptr, (idmef_file_fstype_t **) ret);

                case 14:
                        return idmef_file_new_file_type(ptr, (prelude_string_t **) ret);

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_file_destroy_child(void *p, idmef_class_child_id_t child, int n)
{
        idmef_file_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        if ( ptr->ident ) {
                                prelude_string_destroy(ptr->ident);
                                ptr->ident = NULL;
                        }

                        return 0;

                case 1:
                        if ( ptr->name ) {
                                prelude_string_destroy(ptr->name);
                                ptr->name = NULL;
                        }

                        return 0;

                case 2:
                        if ( ptr->path ) {
                                prelude_string_destroy(ptr->path);
                                ptr->path = NULL;
                        }

                        return 0;

                case 3:
                        if ( ptr->create_time ) {
                                idmef_time_destroy(ptr->create_time);
                                ptr->create_time = NULL;
                        }

                        return 0;

                case 4:
                        if ( ptr->modify_time ) {
                                idmef_time_destroy(ptr->modify_time);
                                ptr->modify_time = NULL;
                        }

                        return 0;

                case 5:
                        if ( ptr->access_time ) {
                                idmef_time_destroy(ptr->access_time);
                                ptr->access_time = NULL;
                        }

                        return 0;

                case 6:
                        ptr->data_size_is_set = 0;
                        return 0;

                case 7:
                        ptr->disk_size_is_set = 0;
                        return 0;

                case 8: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->file_access_list, tmp) {
                                       if ( i++ == n ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               idmef_file_access_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->file_access_list, tmp) {
                                       if ( i++ == pos ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               idmef_file_access_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }
                }

                case 9: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->linkage_list, tmp) {
                                       if ( i++ == n ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               idmef_linkage_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->linkage_list, tmp) {
                                       if ( i++ == pos ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               idmef_linkage_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }
                }

                case 10:
                        if ( ptr->inode ) {
                                idmef_inode_destroy(ptr->inode);
                                ptr->inode = NULL;
                        }

                        return 0;

                case 11: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->checksum_list, tmp) {
                                       if ( i++ == n ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               idmef_checksum_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->checksum_list, tmp) {
                                       if ( i++ == pos ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               idmef_checksum_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }
                }

                case 12:
                        ptr->category = 0;
                        return 0;

                case 13:
                        ptr->fstype_is_set = 0;
                        return 0;

                case 14:
                        if ( ptr->file_type ) {
                                prelude_string_destroy(ptr->file_type);
                                ptr->file_type = NULL;
                        }

                        return 0;

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

static void idmef_file_destroy_internal(idmef_file_t *ptr)
{
        prelude_return_if_fail(ptr);

       if ( ! prelude_list_is_empty(&((prelude_linked_object_t *)ptr)->_list) )
               prelude_list_del_init(&((prelude_linked_object_t *)ptr)->_list);
    
        if ( ptr->ident ) {
                prelude_string_destroy(ptr->ident);
                ptr->ident = NULL;
        }

        if ( ptr->name ) {
                prelude_string_destroy(ptr->name);
                ptr->name = NULL;
        }

        if ( ptr->path ) {
                prelude_string_destroy(ptr->path);
                ptr->path = NULL;
        }

        if ( ptr->create_time ) {
                idmef_time_destroy(ptr->create_time);
                ptr->create_time = NULL;
        }

        if ( ptr->modify_time ) {
                idmef_time_destroy(ptr->modify_time);
                ptr->modify_time = NULL;
        }

        if ( ptr->access_time ) {
                idmef_time_destroy(ptr->access_time);
                ptr->access_time = NULL;
        }

        {
                prelude_list_t *n, *tmp;
                idmef_file_access_t *entry;

                prelude_list_for_each_safe(&ptr->file_access_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        prelude_list_del_init(tmp);
                        idmef_file_access_destroy(entry);
                }
        }

        {
                prelude_list_t *n, *tmp;
                idmef_linkage_t *entry;

                prelude_list_for_each_safe(&ptr->linkage_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        prelude_list_del_init(tmp);
                        idmef_linkage_destroy(entry);
                }
        }

        if ( ptr->inode ) {
                idmef_inode_destroy(ptr->inode);
                ptr->inode = NULL;
        }

        {
                prelude_list_t *n, *tmp;
                idmef_checksum_t *entry;

                prelude_list_for_each_safe(&ptr->checksum_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        prelude_list_del_init(tmp);
                        idmef_checksum_destroy(entry);
                }
        }

        if ( ptr->file_type ) {
                prelude_string_destroy(ptr->file_type);
                ptr->file_type = NULL;
        }


        /* free() should be done by the caller */
}

/**
 * idmef_file_destroy:
 * @ptr: pointer to a #idmef_file_t object.
 *
 * Destroy @ptr and all of it's children.
 * The objects are only destroyed if their reference count reach zero.
 */

void idmef_file_destroy(idmef_file_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( --ptr->refcount )
                return;

        idmef_file_destroy_internal(ptr);
        free(ptr);
}

/**
 * idmef_file_get_ident:
 * @ptr: pointer to a #idmef_file_t object.
 *
 * Get ident children of the #idmef_file_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_file_get_ident(idmef_file_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->ident;
}

/**
 * idmef_file_set_ident:
 * @ptr: pointer to a #idmef_file_t object.
 * @ident: pointer to a #prelude_string_t object.
 *
 * Set @ident object as a children of @ptr.
 * if @ptr already contain an @ident object, then it is destroyed,
 * and updated to point to the provided @ident object.
 */

void idmef_file_set_ident(idmef_file_t *ptr, prelude_string_t *ident)
{
        prelude_return_if_fail(ptr);

        if ( ptr->ident )
                prelude_string_destroy(ptr->ident);

        ptr->ident = ident;
}

/**
 * idmef_file_new_ident:
 * @ptr: pointer to a #idmef_file_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new ident object, children of #idmef_file_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_file_new_ident(idmef_file_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->ident ) {
                retval = prelude_string_new(&ptr->ident);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->ident;
        return 0;
}

/**
 * idmef_file_get_name:
 * @ptr: pointer to a #idmef_file_t object.
 *
 * Get name children of the #idmef_file_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_file_get_name(idmef_file_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->name;
}

/**
 * idmef_file_set_name:
 * @ptr: pointer to a #idmef_file_t object.
 * @name: pointer to a #prelude_string_t object.
 *
 * Set @name object as a children of @ptr.
 * if @ptr already contain an @name object, then it is destroyed,
 * and updated to point to the provided @name object.
 */

void idmef_file_set_name(idmef_file_t *ptr, prelude_string_t *name)
{
        prelude_return_if_fail(ptr);

        if ( ptr->name )
                prelude_string_destroy(ptr->name);

        ptr->name = name;
}

/**
 * idmef_file_new_name:
 * @ptr: pointer to a #idmef_file_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new name object, children of #idmef_file_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_file_new_name(idmef_file_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->name ) {
                retval = prelude_string_new(&ptr->name);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->name;
        return 0;
}

/**
 * idmef_file_get_path:
 * @ptr: pointer to a #idmef_file_t object.
 *
 * Get path children of the #idmef_file_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_file_get_path(idmef_file_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->path;
}

/**
 * idmef_file_set_path:
 * @ptr: pointer to a #idmef_file_t object.
 * @path: pointer to a #prelude_string_t object.
 *
 * Set @path object as a children of @ptr.
 * if @ptr already contain an @path object, then it is destroyed,
 * and updated to point to the provided @path object.
 */

void idmef_file_set_path(idmef_file_t *ptr, prelude_string_t *path)
{
        prelude_return_if_fail(ptr);

        if ( ptr->path )
                prelude_string_destroy(ptr->path);

        ptr->path = path;
}

/**
 * idmef_file_new_path:
 * @ptr: pointer to a #idmef_file_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new path object, children of #idmef_file_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_file_new_path(idmef_file_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->path ) {
                retval = prelude_string_new(&ptr->path);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->path;
        return 0;
}

/**
 * idmef_file_get_create_time:
 * @ptr: pointer to a #idmef_file_t object.
 *
 * Get create_time children of the #idmef_file_t object.
 *
 * Returns: a pointer to a idmef_time_t object, or NULL if the children object is not set.
 */
idmef_time_t *idmef_file_get_create_time(idmef_file_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->create_time;
}

/**
 * idmef_file_set_create_time:
 * @ptr: pointer to a #idmef_file_t object.
 * @create_time: pointer to a #idmef_time_t object.
 *
 * Set @create_time object as a children of @ptr.
 * if @ptr already contain an @create_time object, then it is destroyed,
 * and updated to point to the provided @create_time object.
 */

void idmef_file_set_create_time(idmef_file_t *ptr, idmef_time_t *create_time)
{
        prelude_return_if_fail(ptr);

        if ( ptr->create_time )
                idmef_time_destroy(ptr->create_time);

        ptr->create_time = create_time;
}

/**
 * idmef_file_new_create_time:
 * @ptr: pointer to a #idmef_file_t object.
 * @ret: pointer to an address where to store the created #idmef_time_t object.
 *
 * Create a new create_time object, children of #idmef_file_t.
 * If @ptr already contain a #idmef_time_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_file_new_create_time(idmef_file_t *ptr, idmef_time_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->create_time ) {
                retval = idmef_time_new(&ptr->create_time);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->create_time;
        return 0;
}

/**
 * idmef_file_get_modify_time:
 * @ptr: pointer to a #idmef_file_t object.
 *
 * Get modify_time children of the #idmef_file_t object.
 *
 * Returns: a pointer to a idmef_time_t object, or NULL if the children object is not set.
 */
idmef_time_t *idmef_file_get_modify_time(idmef_file_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->modify_time;
}

/**
 * idmef_file_set_modify_time:
 * @ptr: pointer to a #idmef_file_t object.
 * @modify_time: pointer to a #idmef_time_t object.
 *
 * Set @modify_time object as a children of @ptr.
 * if @ptr already contain an @modify_time object, then it is destroyed,
 * and updated to point to the provided @modify_time object.
 */

void idmef_file_set_modify_time(idmef_file_t *ptr, idmef_time_t *modify_time)
{
        prelude_return_if_fail(ptr);

        if ( ptr->modify_time )
                idmef_time_destroy(ptr->modify_time);

        ptr->modify_time = modify_time;
}

/**
 * idmef_file_new_modify_time:
 * @ptr: pointer to a #idmef_file_t object.
 * @ret: pointer to an address where to store the created #idmef_time_t object.
 *
 * Create a new modify_time object, children of #idmef_file_t.
 * If @ptr already contain a #idmef_time_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_file_new_modify_time(idmef_file_t *ptr, idmef_time_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->modify_time ) {
                retval = idmef_time_new(&ptr->modify_time);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->modify_time;
        return 0;
}

/**
 * idmef_file_get_access_time:
 * @ptr: pointer to a #idmef_file_t object.
 *
 * Get access_time children of the #idmef_file_t object.
 *
 * Returns: a pointer to a idmef_time_t object, or NULL if the children object is not set.
 */
idmef_time_t *idmef_file_get_access_time(idmef_file_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->access_time;
}

/**
 * idmef_file_set_access_time:
 * @ptr: pointer to a #idmef_file_t object.
 * @access_time: pointer to a #idmef_time_t object.
 *
 * Set @access_time object as a children of @ptr.
 * if @ptr already contain an @access_time object, then it is destroyed,
 * and updated to point to the provided @access_time object.
 */

void idmef_file_set_access_time(idmef_file_t *ptr, idmef_time_t *access_time)
{
        prelude_return_if_fail(ptr);

        if ( ptr->access_time )
                idmef_time_destroy(ptr->access_time);

        ptr->access_time = access_time;
}

/**
 * idmef_file_new_access_time:
 * @ptr: pointer to a #idmef_file_t object.
 * @ret: pointer to an address where to store the created #idmef_time_t object.
 *
 * Create a new access_time object, children of #idmef_file_t.
 * If @ptr already contain a #idmef_time_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_file_new_access_time(idmef_file_t *ptr, idmef_time_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->access_time ) {
                retval = idmef_time_new(&ptr->access_time);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->access_time;
        return 0;
}

/**
 * idmef_file_get_data_size:
 * @ptr: pointer to a #idmef_file_t object.
 *
 * Get data_size children of the #idmef_file_t object.
 *
 * Returns: a pointer to a uint64_t object, or NULL if the children object is not set.
 */
uint64_t *idmef_file_get_data_size(idmef_file_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->data_size_is_set ? &ptr->data_size : NULL;
}

/**
 * idmef_file_set_data_size:
 * @ptr: pointer to a #idmef_file_t object.
 * @data_size: pointer to a #uint64_t object.
 *
 * Set @data_size object as a children of @ptr.
 * if @ptr already contain an @data_size object, then it is destroyed,
 * and updated to point to the provided @data_size object.
 */

void idmef_file_set_data_size(idmef_file_t *ptr, uint64_t data_size)
{
        prelude_return_if_fail(ptr);
        ptr->data_size = data_size;
        ptr->data_size_is_set = 1;
}


void idmef_file_unset_data_size(idmef_file_t *ptr)
{
        prelude_return_if_fail(ptr);
        ptr->data_size_is_set = 0;
}


/**
 * idmef_file_new_data_size:
 * @ptr: pointer to a #idmef_file_t object.
 * @ret: pointer to an address where to store the created #uint64_t object.
 *
 * Create a new data_size object, children of #idmef_file_t.
 * If @ptr already contain a #uint64_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_file_new_data_size(idmef_file_t *ptr, uint64_t **ret)
{
        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));
        ptr->data_size_is_set = 1;

        *ret = &ptr->data_size;
        return 0;
}

/**
 * idmef_file_get_disk_size:
 * @ptr: pointer to a #idmef_file_t object.
 *
 * Get disk_size children of the #idmef_file_t object.
 *
 * Returns: a pointer to a uint64_t object, or NULL if the children object is not set.
 */
uint64_t *idmef_file_get_disk_size(idmef_file_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->disk_size_is_set ? &ptr->disk_size : NULL;
}

/**
 * idmef_file_set_disk_size:
 * @ptr: pointer to a #idmef_file_t object.
 * @disk_size: pointer to a #uint64_t object.
 *
 * Set @disk_size object as a children of @ptr.
 * if @ptr already contain an @disk_size object, then it is destroyed,
 * and updated to point to the provided @disk_size object.
 */

void idmef_file_set_disk_size(idmef_file_t *ptr, uint64_t disk_size)
{
        prelude_return_if_fail(ptr);
        ptr->disk_size = disk_size;
        ptr->disk_size_is_set = 1;
}


void idmef_file_unset_disk_size(idmef_file_t *ptr)
{
        prelude_return_if_fail(ptr);
        ptr->disk_size_is_set = 0;
}


/**
 * idmef_file_new_disk_size:
 * @ptr: pointer to a #idmef_file_t object.
 * @ret: pointer to an address where to store the created #uint64_t object.
 *
 * Create a new disk_size object, children of #idmef_file_t.
 * If @ptr already contain a #uint64_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_file_new_disk_size(idmef_file_t *ptr, uint64_t **ret)
{
        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));
        ptr->disk_size_is_set = 1;

        *ret = &ptr->disk_size;
        return 0;
}

/**
 * idmef_file_get_next_file_access:
 * @file: pointer to a #idmef_file_t object.
 * @file_access_cur: pointer to a #idmef_file_access_t object.
 *
 * Get the next #idmef_file_access_t object listed in @ptr.
 * When iterating over the idmef_file_access_t object listed in @ptr,
 * @object should be set to the latest returned #idmef_file_access_t object.
 *
 * Returns: the next #idmef_file_access_t in the list.
 */
idmef_file_access_t *idmef_file_get_next_file_access(idmef_file_t *file, idmef_file_access_t *file_access_cur)
{
        prelude_list_t *tmp = (file_access_cur) ? &((prelude_linked_object_t *) file_access_cur)->_list : NULL;

        prelude_return_val_if_fail(file, NULL);

        prelude_list_for_each_continue(&file->file_access_list, tmp)
                return prelude_linked_object_get_object(tmp);

        return NULL;
}


/**
 * idmef_file_set_file_access:
 * @ptr: pointer to a #idmef_file_t object.
 * @object: pointer to a #idmef_file_access_t object.
 * @pos: Position in the list.
 *
 * Add @object to position @pos of @ptr list of #idmef_file_access_t object.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 */
void idmef_file_set_file_access(idmef_file_t *ptr, idmef_file_access_t *object, int pos)
{
        prelude_return_if_fail(ptr);
        prelude_return_if_fail(object);

        if ( ! prelude_list_is_empty(&((prelude_linked_object_t *) object)->_list) )
                prelude_list_del_init(&((prelude_linked_object_t *) object)->_list);

        list_insert(&ptr->file_access_list, &((prelude_linked_object_t *) object)->_list, pos);
}


/**
 * idmef_file_new_file_access:
 * @ptr: pointer to a #idmef_file_t object.
 * @ret: pointer to an address where to store the created #idmef_file_access_t object.
 * @pos: position in the list.
 *
 * Create a new #idmef_file_access_t children of @ptr, and add it to position @pos of
 * @ptr list of #idmef_file_access_t object. The created #idmef_file_access_t object is
 * stored in @ret.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_file_new_file_access(idmef_file_t *ptr, idmef_file_access_t **ret, int pos)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        retval = idmef_file_access_new(ret);
        if ( retval < 0 )
                return retval;

        list_insert(&ptr->file_access_list, &((prelude_linked_object_t *)(*ret))->_list, pos);

        return 0;
}


/**
 * idmef_file_get_next_linkage:
 * @file: pointer to a #idmef_file_t object.
 * @linkage_cur: pointer to a #idmef_linkage_t object.
 *
 * Get the next #idmef_linkage_t object listed in @ptr.
 * When iterating over the idmef_linkage_t object listed in @ptr,
 * @object should be set to the latest returned #idmef_linkage_t object.
 *
 * Returns: the next #idmef_linkage_t in the list.
 */
idmef_linkage_t *idmef_file_get_next_linkage(idmef_file_t *file, idmef_linkage_t *linkage_cur)
{
        prelude_list_t *tmp = (linkage_cur) ? &((prelude_linked_object_t *) linkage_cur)->_list : NULL;

        prelude_return_val_if_fail(file, NULL);

        prelude_list_for_each_continue(&file->linkage_list, tmp)
                return prelude_linked_object_get_object(tmp);

        return NULL;
}


/**
 * idmef_file_set_linkage:
 * @ptr: pointer to a #idmef_file_t object.
 * @object: pointer to a #idmef_linkage_t object.
 * @pos: Position in the list.
 *
 * Add @object to position @pos of @ptr list of #idmef_linkage_t object.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 */
void idmef_file_set_linkage(idmef_file_t *ptr, idmef_linkage_t *object, int pos)
{
        prelude_return_if_fail(ptr);
        prelude_return_if_fail(object);

        if ( ! prelude_list_is_empty(&((prelude_linked_object_t *) object)->_list) )
                prelude_list_del_init(&((prelude_linked_object_t *) object)->_list);

        list_insert(&ptr->linkage_list, &((prelude_linked_object_t *) object)->_list, pos);
}


/**
 * idmef_file_new_linkage:
 * @ptr: pointer to a #idmef_file_t object.
 * @ret: pointer to an address where to store the created #idmef_linkage_t object.
 * @pos: position in the list.
 *
 * Create a new #idmef_linkage_t children of @ptr, and add it to position @pos of
 * @ptr list of #idmef_linkage_t object. The created #idmef_linkage_t object is
 * stored in @ret.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_file_new_linkage(idmef_file_t *ptr, idmef_linkage_t **ret, int pos)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        retval = idmef_linkage_new(ret);
        if ( retval < 0 )
                return retval;

        list_insert(&ptr->linkage_list, &((prelude_linked_object_t *)(*ret))->_list, pos);

        return 0;
}


/**
 * idmef_file_get_inode:
 * @ptr: pointer to a #idmef_file_t object.
 *
 * Get inode children of the #idmef_file_t object.
 *
 * Returns: a pointer to a idmef_inode_t object, or NULL if the children object is not set.
 */
idmef_inode_t *idmef_file_get_inode(idmef_file_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->inode;
}

/**
 * idmef_file_set_inode:
 * @ptr: pointer to a #idmef_file_t object.
 * @inode: pointer to a #idmef_inode_t object.
 *
 * Set @inode object as a children of @ptr.
 * if @ptr already contain an @inode object, then it is destroyed,
 * and updated to point to the provided @inode object.
 */

void idmef_file_set_inode(idmef_file_t *ptr, idmef_inode_t *inode)
{
        prelude_return_if_fail(ptr);

        if ( ptr->inode )
                idmef_inode_destroy(ptr->inode);

        ptr->inode = inode;
}

/**
 * idmef_file_new_inode:
 * @ptr: pointer to a #idmef_file_t object.
 * @ret: pointer to an address where to store the created #idmef_inode_t object.
 *
 * Create a new inode object, children of #idmef_file_t.
 * If @ptr already contain a #idmef_inode_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_file_new_inode(idmef_file_t *ptr, idmef_inode_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->inode ) {
                retval = idmef_inode_new(&ptr->inode);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->inode;
        return 0;
}

/**
 * idmef_file_get_next_checksum:
 * @file: pointer to a #idmef_file_t object.
 * @checksum_cur: pointer to a #idmef_checksum_t object.
 *
 * Get the next #idmef_checksum_t object listed in @ptr.
 * When iterating over the idmef_checksum_t object listed in @ptr,
 * @object should be set to the latest returned #idmef_checksum_t object.
 *
 * Returns: the next #idmef_checksum_t in the list.
 */
idmef_checksum_t *idmef_file_get_next_checksum(idmef_file_t *file, idmef_checksum_t *checksum_cur)
{
        prelude_list_t *tmp = (checksum_cur) ? &((prelude_linked_object_t *) checksum_cur)->_list : NULL;

        prelude_return_val_if_fail(file, NULL);

        prelude_list_for_each_continue(&file->checksum_list, tmp)
                return prelude_linked_object_get_object(tmp);

        return NULL;
}


/**
 * idmef_file_set_checksum:
 * @ptr: pointer to a #idmef_file_t object.
 * @object: pointer to a #idmef_checksum_t object.
 * @pos: Position in the list.
 *
 * Add @object to position @pos of @ptr list of #idmef_checksum_t object.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 */
void idmef_file_set_checksum(idmef_file_t *ptr, idmef_checksum_t *object, int pos)
{
        prelude_return_if_fail(ptr);
        prelude_return_if_fail(object);

        if ( ! prelude_list_is_empty(&((prelude_linked_object_t *) object)->_list) )
                prelude_list_del_init(&((prelude_linked_object_t *) object)->_list);

        list_insert(&ptr->checksum_list, &((prelude_linked_object_t *) object)->_list, pos);
}


/**
 * idmef_file_new_checksum:
 * @ptr: pointer to a #idmef_file_t object.
 * @ret: pointer to an address where to store the created #idmef_checksum_t object.
 * @pos: position in the list.
 *
 * Create a new #idmef_checksum_t children of @ptr, and add it to position @pos of
 * @ptr list of #idmef_checksum_t object. The created #idmef_checksum_t object is
 * stored in @ret.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_file_new_checksum(idmef_file_t *ptr, idmef_checksum_t **ret, int pos)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        retval = idmef_checksum_new(ret);
        if ( retval < 0 )
                return retval;

        list_insert(&ptr->checksum_list, &((prelude_linked_object_t *)(*ret))->_list, pos);

        return 0;
}


/**
 * idmef_file_get_category:
 * @ptr: pointer to a #idmef_file_t object.
 *
 * Get category children of the #idmef_file_t object.
 *
 * Returns: a pointer to a idmef_file_category_t object, or NULL if the children object is not set.
 */
idmef_file_category_t idmef_file_get_category(idmef_file_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->category;
}

/**
 * idmef_file_set_category:
 * @ptr: pointer to a #idmef_file_t object.
 * @category: pointer to a #idmef_file_category_t object.
 *
 * Set @category object as a children of @ptr.
 * if @ptr already contain an @category object, then it is destroyed,
 * and updated to point to the provided @category object.
 */

void idmef_file_set_category(idmef_file_t *ptr, idmef_file_category_t category)
{
        prelude_return_if_fail(ptr);
        ptr->category = category;
}

/**
 * idmef_file_new_category:
 * @ptr: pointer to a #idmef_file_t object.
 * @ret: pointer to an address where to store the created #idmef_file_category_t object.
 *
 * Create a new category object, children of #idmef_file_t.
 * If @ptr already contain a #idmef_file_category_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_file_new_category(idmef_file_t *ptr, idmef_file_category_t **ret)
{
        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        *ret = &ptr->category;
        return 0;
}

/**
 * idmef_file_get_fstype:
 * @ptr: pointer to a #idmef_file_t object.
 *
 * Get fstype children of the #idmef_file_t object.
 *
 * Returns: a pointer to a idmef_file_fstype_t object, or NULL if the children object is not set.
 */
idmef_file_fstype_t *idmef_file_get_fstype(idmef_file_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->fstype_is_set ? &ptr->fstype : NULL;
}

/**
 * idmef_file_set_fstype:
 * @ptr: pointer to a #idmef_file_t object.
 * @fstype: pointer to a #idmef_file_fstype_t object.
 *
 * Set @fstype object as a children of @ptr.
 * if @ptr already contain an @fstype object, then it is destroyed,
 * and updated to point to the provided @fstype object.
 */

void idmef_file_set_fstype(idmef_file_t *ptr, idmef_file_fstype_t fstype)
{
        prelude_return_if_fail(ptr);
        ptr->fstype = fstype;
        ptr->fstype_is_set = 1;
}


void idmef_file_unset_fstype(idmef_file_t *ptr)
{
        prelude_return_if_fail(ptr);
        ptr->fstype_is_set = 0;
}


/**
 * idmef_file_new_fstype:
 * @ptr: pointer to a #idmef_file_t object.
 * @ret: pointer to an address where to store the created #idmef_file_fstype_t object.
 *
 * Create a new fstype object, children of #idmef_file_t.
 * If @ptr already contain a #idmef_file_fstype_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_file_new_fstype(idmef_file_t *ptr, idmef_file_fstype_t **ret)
{
        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));
        ptr->fstype_is_set = 1;

        *ret = &ptr->fstype;
        return 0;
}

/**
 * idmef_file_get_file_type:
 * @ptr: pointer to a #idmef_file_t object.
 *
 * Get file_type children of the #idmef_file_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_file_get_file_type(idmef_file_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->file_type;
}

/**
 * idmef_file_set_file_type:
 * @ptr: pointer to a #idmef_file_t object.
 * @file_type: pointer to a #prelude_string_t object.
 *
 * Set @file_type object as a children of @ptr.
 * if @ptr already contain an @file_type object, then it is destroyed,
 * and updated to point to the provided @file_type object.
 */

void idmef_file_set_file_type(idmef_file_t *ptr, prelude_string_t *file_type)
{
        prelude_return_if_fail(ptr);

        if ( ptr->file_type )
                prelude_string_destroy(ptr->file_type);

        ptr->file_type = file_type;
}

/**
 * idmef_file_new_file_type:
 * @ptr: pointer to a #idmef_file_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new file_type object, children of #idmef_file_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_file_new_file_type(idmef_file_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->file_type ) {
                retval = prelude_string_new(&ptr->file_type);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->file_type;
        return 0;
}

/**
 * idmef_file_copy:
 * @src: Source of the copy.
 * @dst: Where to copy the object.
 *
 * Copy a new #idmef_file_t object from @src to @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_file_copy(const idmef_file_t *src, idmef_file_t *dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));
        prelude_return_val_if_fail(dst, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = 0;

        if ( dst->ident ) {
                prelude_string_destroy(dst->ident);
                dst->ident = NULL;
        }

        if ( src->ident ) {
                ret = prelude_string_clone(src->ident, &dst->ident);
                if ( ret < 0 )
                        return ret;
        }

        if ( src->name ) {
                ret = prelude_string_copy(src->name, dst->name);
                if ( ret < 0 )
                        return ret;
        }

        if ( src->path ) {
                ret = prelude_string_copy(src->path, dst->path);
                if ( ret < 0 )
                        return ret;
        }

        if ( dst->create_time ) {
                idmef_time_destroy(dst->create_time);
                dst->create_time = NULL;
        }

        if ( src->create_time ) {
                ret = idmef_time_clone(src->create_time, &dst->create_time);
                if ( ret < 0 )
                        return ret;
        }

        if ( dst->modify_time ) {
                idmef_time_destroy(dst->modify_time);
                dst->modify_time = NULL;
        }

        if ( src->modify_time ) {
                ret = idmef_time_clone(src->modify_time, &dst->modify_time);
                if ( ret < 0 )
                        return ret;
        }

        if ( dst->access_time ) {
                idmef_time_destroy(dst->access_time);
                dst->access_time = NULL;
        }

        if ( src->access_time ) {
                ret = idmef_time_clone(src->access_time, &dst->access_time);
                if ( ret < 0 )
                        return ret;
        }

        dst->data_size_is_set = src->data_size_is_set;

        dst->data_size = src->data_size;

        dst->disk_size_is_set = src->disk_size_is_set;

        dst->disk_size = src->disk_size;

        {
                prelude_list_t *n, *tmp;
                idmef_file_access_t *entry, *new;

                prelude_list_for_each_safe(&dst->file_access_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        idmef_file_access_destroy(entry);
                }

                prelude_list_for_each_safe(&src->file_access_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        idmef_file_access_clone(entry, &new);
                        prelude_list_add_tail(&dst->file_access_list, &((prelude_linked_object_t *) new)->_list);
                }
        }

        {
                prelude_list_t *n, *tmp;
                idmef_linkage_t *entry, *new;

                prelude_list_for_each_safe(&dst->linkage_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        idmef_linkage_destroy(entry);
                }

                prelude_list_for_each_safe(&src->linkage_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        idmef_linkage_clone(entry, &new);
                        prelude_list_add_tail(&dst->linkage_list, &((prelude_linked_object_t *) new)->_list);
                }
        }

        if ( dst->inode ) {
                idmef_inode_destroy(dst->inode);
                dst->inode = NULL;
        }

        if ( src->inode ) {
                ret = idmef_inode_clone(src->inode, &dst->inode);
                if ( ret < 0 )
                        return ret;
        }

        {
                prelude_list_t *n, *tmp;
                idmef_checksum_t *entry, *new;

                prelude_list_for_each_safe(&dst->checksum_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        idmef_checksum_destroy(entry);
                }

                prelude_list_for_each_safe(&src->checksum_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        idmef_checksum_clone(entry, &new);
                        prelude_list_add_tail(&dst->checksum_list, &((prelude_linked_object_t *) new)->_list);
                }
        }

        dst->category = src->category;

        dst->fstype_is_set = src->fstype_is_set;

        dst->fstype = src->fstype;

        if ( dst->file_type ) {
                prelude_string_destroy(dst->file_type);
                dst->file_type = NULL;
        }

        if ( src->file_type ) {
                ret = prelude_string_clone(src->file_type, &dst->file_type);
                if ( ret < 0 )
                        return ret;
        }

        return 0;
}

/**
 * idmef_file_clone:
 * @src: Object to be cloned.
 * @dst: Address where to store the pointer to the cloned object.
 *
 * Create a copy of @src, and store it in @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_file_clone(idmef_file_t *src, idmef_file_t **dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = idmef_file_new(dst);
        if ( ret < 0 )
                return ret;

        return idmef_file_copy(src, *dst);
}

/**
 * idmef_file_compare:
 * @obj1: Object to compare with @obj2.
 * @obj2: Object to compare with @obj1.
 *
 * Compare @obj1 with @obj2.
 *
 * Returns: 0 on match, a negative value on comparison failure.
 */
int idmef_file_compare(const idmef_file_t *obj1, const idmef_file_t *obj2)
{
        int ret = 0;

        if ( obj1 == NULL && obj2 == NULL )
                return 0;

        else if ( obj1 == NULL || obj2 == NULL )
                return -1;

        ret = prelude_string_compare(obj1->ident, obj2->ident);
        if ( ret != 0 )
                return ret;

        ret = prelude_string_compare(obj1->name, obj2->name);
        if ( ret != 0 )
                return ret;

        ret = prelude_string_compare(obj1->path, obj2->path);
        if ( ret != 0 )
                return ret;

        ret = idmef_time_compare(obj1->create_time, obj2->create_time);
        if ( ret != 0 )
                return ret;

        ret = idmef_time_compare(obj1->modify_time, obj2->modify_time);
        if ( ret != 0 )
                return ret;

        ret = idmef_time_compare(obj1->access_time, obj2->access_time);
        if ( ret != 0 )
                return ret;

        if ( obj1->data_size_is_set != obj2->data_size_is_set )
                return -1;

        if ( obj1->data_size_is_set && obj1->data_size != obj2->data_size )
                return -1;

        if ( obj1->disk_size_is_set != obj2->disk_size_is_set )
                return -1;

        if ( obj1->disk_size_is_set && obj1->disk_size != obj2->disk_size )
                return -1;

        {
                prelude_list_t *tmp1, *tmp2;
                idmef_file_access_t *entry1, *entry2;

                tmp1 = tmp2 = NULL;
                do {
                        entry1 = entry2 = NULL;

                        prelude_list_for_each_continue(&obj1->file_access_list, tmp1) {
                                entry1 = prelude_linked_object_get_object(tmp1);
                                break;
                        }

                        prelude_list_for_each_continue(&obj2->file_access_list, tmp2) {
                                entry2 = prelude_linked_object_get_object(tmp2);
                                break;
                        }

                        ret = idmef_file_access_compare(entry1, entry2);
                        if ( ret != 0 )
                                return ret;

                } while ( entry1 && entry2 );
        }

        {
                prelude_list_t *tmp1, *tmp2;
                idmef_linkage_t *entry1, *entry2;

                tmp1 = tmp2 = NULL;
                do {
                        entry1 = entry2 = NULL;

                        prelude_list_for_each_continue(&obj1->linkage_list, tmp1) {
                                entry1 = prelude_linked_object_get_object(tmp1);
                                break;
                        }

                        prelude_list_for_each_continue(&obj2->linkage_list, tmp2) {
                                entry2 = prelude_linked_object_get_object(tmp2);
                                break;
                        }

                        ret = idmef_linkage_compare(entry1, entry2);
                        if ( ret != 0 )
                                return ret;

                } while ( entry1 && entry2 );
        }

        ret = idmef_inode_compare(obj1->inode, obj2->inode);
        if ( ret != 0 )
                return ret;

        {
                prelude_list_t *tmp1, *tmp2;
                idmef_checksum_t *entry1, *entry2;

                tmp1 = tmp2 = NULL;
                do {
                        entry1 = entry2 = NULL;

                        prelude_list_for_each_continue(&obj1->checksum_list, tmp1) {
                                entry1 = prelude_linked_object_get_object(tmp1);
                                break;
                        }

                        prelude_list_for_each_continue(&obj2->checksum_list, tmp2) {
                                entry2 = prelude_linked_object_get_object(tmp2);
                                break;
                        }

                        ret = idmef_checksum_compare(entry1, entry2);
                        if ( ret != 0 )
                                return ret;

                } while ( entry1 && entry2 );
        }

        if ( obj1->category != obj2->category )
                return -1;

        if ( obj1->fstype_is_set != obj2->fstype_is_set )
                return -1;

        if ( obj1->fstype_is_set && obj1->fstype != obj2->fstype )
                return -1;

        ret = prelude_string_compare(obj1->file_type, obj2->file_type);
        if ( ret != 0 )
                return ret;

        return ret;
}

/**
 * idmef_linkage_new:
 * @ret: Pointer where to store the created #idmef_linkage_t object.
 *
 * Create a new #idmef_linkage_t object.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_linkage_new(idmef_linkage_t **ret)
{
        *ret = calloc(1, sizeof(**ret));
        if ( ! *ret )
                return prelude_error_from_errno(errno);

        (*ret)->_idmef_object_id = IDMEF_CLASS_ID_LINKAGE;

        prelude_list_init(&((prelude_linked_object_t *) (*ret))->_list);

        (*ret)->refcount = 1;

        {
                int retval = prelude_string_new(&(*ret)->name);

                if ( retval < 0 ) {
                        idmef_linkage_destroy(*ret);
                        *ret = NULL;
                        return retval;
                }
        }

        {
                int retval = prelude_string_new(&(*ret)->path);

                if ( retval < 0 ) {
                        idmef_linkage_destroy(*ret);
                        *ret = NULL;
                        return retval;
                }
        }

        {
                int retval = idmef_file_new(&(*ret)->file);

                if ( retval < 0 ) {
                        idmef_linkage_destroy(*ret);
                        *ret = NULL;
                        return retval;
                }
        }

        return 0;

}

/**
 * idmef_linkage_ref:
 * @linkage: pointer to a #idmef_linkage_t object.
 *
 * Increase @linkage reference count, so that it can be referenced
 * multiple time.
 *
 * Returns: a pointer to @linkage.
 */
idmef_linkage_t *idmef_linkage_ref(idmef_linkage_t *linkage)
{
        prelude_return_val_if_fail(linkage, NULL);
        linkage->refcount++;

        return linkage;
}

int _idmef_linkage_get_child(void *p, idmef_class_child_id_t child, void **childptr)
{
        idmef_linkage_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));
        *childptr = NULL;

        switch ( child ) {

                case 0:
                       return idmef_value_new_enum_from_numeric((idmef_value_t **) childptr,
                                                                IDMEF_CLASS_ID_LINKAGE_CATEGORY, ptr->category);

                case 1:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->name, TRUE);
                case 2:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->path, TRUE);
                case 3:
                        *childptr = ptr->file;
                        return 0;

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_linkage_new_child(void *p, idmef_class_child_id_t child, int n, void **ret)
{
        idmef_linkage_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        return idmef_linkage_new_category(ptr, (idmef_linkage_category_t **) ret);

                case 1:
                        return idmef_linkage_new_name(ptr, (prelude_string_t **) ret);

                case 2:
                        return idmef_linkage_new_path(ptr, (prelude_string_t **) ret);

                case 3:
                        return idmef_linkage_new_file(ptr, (idmef_file_t **) ret);

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_linkage_destroy_child(void *p, idmef_class_child_id_t child, int n)
{
        idmef_linkage_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        ptr->category = 0;
                        return 0;

                case 1:
                        if ( ptr->name ) {
                                prelude_string_destroy(ptr->name);
                                ptr->name = NULL;
                        }

                        return 0;

                case 2:
                        if ( ptr->path ) {
                                prelude_string_destroy(ptr->path);
                                ptr->path = NULL;
                        }

                        return 0;

                case 3:
                        if ( ptr->file ) {
                                idmef_file_destroy(ptr->file);
                                ptr->file = NULL;
                        }

                        return 0;

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

static void idmef_linkage_destroy_internal(idmef_linkage_t *ptr)
{
        prelude_return_if_fail(ptr);

       if ( ! prelude_list_is_empty(&((prelude_linked_object_t *)ptr)->_list) )
               prelude_list_del_init(&((prelude_linked_object_t *)ptr)->_list);
    
        if ( ptr->name ) {
                prelude_string_destroy(ptr->name);
                ptr->name = NULL;
        }

        if ( ptr->path ) {
                prelude_string_destroy(ptr->path);
                ptr->path = NULL;
        }

        if ( ptr->file ) {
                idmef_file_destroy(ptr->file);
                ptr->file = NULL;
        }


        /* free() should be done by the caller */
}

/**
 * idmef_linkage_destroy:
 * @ptr: pointer to a #idmef_linkage_t object.
 *
 * Destroy @ptr and all of it's children.
 * The objects are only destroyed if their reference count reach zero.
 */

void idmef_linkage_destroy(idmef_linkage_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( --ptr->refcount )
                return;

        idmef_linkage_destroy_internal(ptr);
        free(ptr);
}

/**
 * idmef_linkage_get_category:
 * @ptr: pointer to a #idmef_linkage_t object.
 *
 * Get category children of the #idmef_linkage_t object.
 *
 * Returns: a pointer to a idmef_linkage_category_t object, or NULL if the children object is not set.
 */
idmef_linkage_category_t idmef_linkage_get_category(idmef_linkage_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->category;
}

/**
 * idmef_linkage_set_category:
 * @ptr: pointer to a #idmef_linkage_t object.
 * @category: pointer to a #idmef_linkage_category_t object.
 *
 * Set @category object as a children of @ptr.
 * if @ptr already contain an @category object, then it is destroyed,
 * and updated to point to the provided @category object.
 */

void idmef_linkage_set_category(idmef_linkage_t *ptr, idmef_linkage_category_t category)
{
        prelude_return_if_fail(ptr);
        ptr->category = category;
}

/**
 * idmef_linkage_new_category:
 * @ptr: pointer to a #idmef_linkage_t object.
 * @ret: pointer to an address where to store the created #idmef_linkage_category_t object.
 *
 * Create a new category object, children of #idmef_linkage_t.
 * If @ptr already contain a #idmef_linkage_category_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_linkage_new_category(idmef_linkage_t *ptr, idmef_linkage_category_t **ret)
{
        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        *ret = &ptr->category;
        return 0;
}

/**
 * idmef_linkage_get_name:
 * @ptr: pointer to a #idmef_linkage_t object.
 *
 * Get name children of the #idmef_linkage_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_linkage_get_name(idmef_linkage_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->name;
}

/**
 * idmef_linkage_set_name:
 * @ptr: pointer to a #idmef_linkage_t object.
 * @name: pointer to a #prelude_string_t object.
 *
 * Set @name object as a children of @ptr.
 * if @ptr already contain an @name object, then it is destroyed,
 * and updated to point to the provided @name object.
 */

void idmef_linkage_set_name(idmef_linkage_t *ptr, prelude_string_t *name)
{
        prelude_return_if_fail(ptr);

        if ( ptr->name )
                prelude_string_destroy(ptr->name);

        ptr->name = name;
}

/**
 * idmef_linkage_new_name:
 * @ptr: pointer to a #idmef_linkage_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new name object, children of #idmef_linkage_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_linkage_new_name(idmef_linkage_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->name ) {
                retval = prelude_string_new(&ptr->name);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->name;
        return 0;
}

/**
 * idmef_linkage_get_path:
 * @ptr: pointer to a #idmef_linkage_t object.
 *
 * Get path children of the #idmef_linkage_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_linkage_get_path(idmef_linkage_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->path;
}

/**
 * idmef_linkage_set_path:
 * @ptr: pointer to a #idmef_linkage_t object.
 * @path: pointer to a #prelude_string_t object.
 *
 * Set @path object as a children of @ptr.
 * if @ptr already contain an @path object, then it is destroyed,
 * and updated to point to the provided @path object.
 */

void idmef_linkage_set_path(idmef_linkage_t *ptr, prelude_string_t *path)
{
        prelude_return_if_fail(ptr);

        if ( ptr->path )
                prelude_string_destroy(ptr->path);

        ptr->path = path;
}

/**
 * idmef_linkage_new_path:
 * @ptr: pointer to a #idmef_linkage_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new path object, children of #idmef_linkage_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_linkage_new_path(idmef_linkage_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->path ) {
                retval = prelude_string_new(&ptr->path);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->path;
        return 0;
}

/**
 * idmef_linkage_get_file:
 * @ptr: pointer to a #idmef_linkage_t object.
 *
 * Get file children of the #idmef_linkage_t object.
 *
 * Returns: a pointer to a idmef_file_t object, or NULL if the children object is not set.
 */
idmef_file_t *idmef_linkage_get_file(idmef_linkage_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->file;
}

/**
 * idmef_linkage_set_file:
 * @ptr: pointer to a #idmef_linkage_t object.
 * @file: pointer to a #idmef_file_t object.
 *
 * Set @file object as a children of @ptr.
 * if @ptr already contain an @file object, then it is destroyed,
 * and updated to point to the provided @file object.
 */

void idmef_linkage_set_file(idmef_linkage_t *ptr, idmef_file_t *file)
{
        prelude_return_if_fail(ptr);

        if ( ptr->file )
                idmef_file_destroy(ptr->file);

        ptr->file = file;
}

/**
 * idmef_linkage_new_file:
 * @ptr: pointer to a #idmef_linkage_t object.
 * @ret: pointer to an address where to store the created #idmef_file_t object.
 *
 * Create a new file object, children of #idmef_linkage_t.
 * If @ptr already contain a #idmef_file_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_linkage_new_file(idmef_linkage_t *ptr, idmef_file_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->file ) {
                retval = idmef_file_new(&ptr->file);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->file;
        return 0;
}

/**
 * idmef_linkage_copy:
 * @src: Source of the copy.
 * @dst: Where to copy the object.
 *
 * Copy a new #idmef_linkage_t object from @src to @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_linkage_copy(const idmef_linkage_t *src, idmef_linkage_t *dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));
        prelude_return_val_if_fail(dst, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = 0;

        dst->category = src->category;

        if ( src->name ) {
                ret = prelude_string_copy(src->name, dst->name);
                if ( ret < 0 )
                        return ret;
        }

        if ( src->path ) {
                ret = prelude_string_copy(src->path, dst->path);
                if ( ret < 0 )
                        return ret;
        }

        if ( src->file ) {
                ret = idmef_file_copy(src->file, dst->file);
                if ( ret < 0 )
                        return ret;
        }

        return 0;
}

/**
 * idmef_linkage_clone:
 * @src: Object to be cloned.
 * @dst: Address where to store the pointer to the cloned object.
 *
 * Create a copy of @src, and store it in @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_linkage_clone(idmef_linkage_t *src, idmef_linkage_t **dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = idmef_linkage_new(dst);
        if ( ret < 0 )
                return ret;

        return idmef_linkage_copy(src, *dst);
}

/**
 * idmef_linkage_compare:
 * @obj1: Object to compare with @obj2.
 * @obj2: Object to compare with @obj1.
 *
 * Compare @obj1 with @obj2.
 *
 * Returns: 0 on match, a negative value on comparison failure.
 */
int idmef_linkage_compare(const idmef_linkage_t *obj1, const idmef_linkage_t *obj2)
{
        int ret = 0;

        if ( obj1 == NULL && obj2 == NULL )
                return 0;

        else if ( obj1 == NULL || obj2 == NULL )
                return -1;

        if ( obj1->category != obj2->category )
                return -1;

        ret = prelude_string_compare(obj1->name, obj2->name);
        if ( ret != 0 )
                return ret;

        ret = prelude_string_compare(obj1->path, obj2->path);
        if ( ret != 0 )
                return ret;

        ret = idmef_file_compare(obj1->file, obj2->file);
        if ( ret != 0 )
                return ret;

        return ret;
}

/**
 * idmef_target_new:
 * @ret: Pointer where to store the created #idmef_target_t object.
 *
 * Create a new #idmef_target_t object.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_target_new(idmef_target_t **ret)
{
        *ret = calloc(1, sizeof(**ret));
        if ( ! *ret )
                return prelude_error_from_errno(errno);

        (*ret)->_idmef_object_id = IDMEF_CLASS_ID_TARGET;

        prelude_list_init(&((prelude_linked_object_t *) (*ret))->_list);

        (*ret)->refcount = 1;

        prelude_list_init(&(*ret)->file_list);


        return 0;

}

/**
 * idmef_target_ref:
 * @target: pointer to a #idmef_target_t object.
 *
 * Increase @target reference count, so that it can be referenced
 * multiple time.
 *
 * Returns: a pointer to @target.
 */
idmef_target_t *idmef_target_ref(idmef_target_t *target)
{
        prelude_return_val_if_fail(target, NULL);
        target->refcount++;

        return target;
}

int _idmef_target_get_child(void *p, idmef_class_child_id_t child, void **childptr)
{
        idmef_target_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));
        *childptr = NULL;

        switch ( child ) {

                case 0:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->ident, TRUE);
                case 1:
                       return idmef_value_new_enum_from_numeric((idmef_value_t **) childptr,
                                                                IDMEF_CLASS_ID_TARGET_DECOY, ptr->decoy);

                case 2:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->interface, TRUE);
                case 3:
                        *childptr = ptr->node;
                        return 0;

                case 4:
                        *childptr = ptr->user;
                        return 0;

                case 5:
                        *childptr = ptr->process;
                        return 0;

                case 6:
                        *childptr = ptr->service;
                        return 0;

                case 7:
                        *childptr = &ptr->file_list;
                        return 0;

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_target_new_child(void *p, idmef_class_child_id_t child, int n, void **ret)
{
        idmef_target_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        return idmef_target_new_ident(ptr, (prelude_string_t **) ret);

                case 1:
                        return idmef_target_new_decoy(ptr, (idmef_target_decoy_t **) ret);

                case 2:
                        return idmef_target_new_interface(ptr, (prelude_string_t **) ret);

                case 3:
                        return idmef_target_new_node(ptr, (idmef_node_t **) ret);

                case 4:
                        return idmef_target_new_user(ptr, (idmef_user_t **) ret);

                case 5:
                        return idmef_target_new_process(ptr, (idmef_process_t **) ret);

                case 6:
                        return idmef_target_new_service(ptr, (idmef_service_t **) ret);

                case 7: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n == IDMEF_LIST_APPEND || n == IDMEF_LIST_PREPEND )
                               return idmef_target_new_file(ptr, (idmef_file_t **) ret, n);

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->file_list, tmp) {
                                       if ( i++ == n ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->file_list, tmp) {
                                       if ( i++ == pos ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }

                        return idmef_target_new_file(ptr, (idmef_file_t **) ret, n);
                }

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_target_destroy_child(void *p, idmef_class_child_id_t child, int n)
{
        idmef_target_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        if ( ptr->ident ) {
                                prelude_string_destroy(ptr->ident);
                                ptr->ident = NULL;
                        }

                        return 0;

                case 1:
                        ptr->decoy = 0;
                        return 0;

                case 2:
                        if ( ptr->interface ) {
                                prelude_string_destroy(ptr->interface);
                                ptr->interface = NULL;
                        }

                        return 0;

                case 3:
                        if ( ptr->node ) {
                                idmef_node_destroy(ptr->node);
                                ptr->node = NULL;
                        }

                        return 0;

                case 4:
                        if ( ptr->user ) {
                                idmef_user_destroy(ptr->user);
                                ptr->user = NULL;
                        }

                        return 0;

                case 5:
                        if ( ptr->process ) {
                                idmef_process_destroy(ptr->process);
                                ptr->process = NULL;
                        }

                        return 0;

                case 6:
                        if ( ptr->service ) {
                                idmef_service_destroy(ptr->service);
                                ptr->service = NULL;
                        }

                        return 0;

                case 7: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->file_list, tmp) {
                                       if ( i++ == n ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               idmef_file_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->file_list, tmp) {
                                       if ( i++ == pos ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               idmef_file_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }
                }

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

static void idmef_target_destroy_internal(idmef_target_t *ptr)
{
        prelude_return_if_fail(ptr);

       if ( ! prelude_list_is_empty(&((prelude_linked_object_t *)ptr)->_list) )
               prelude_list_del_init(&((prelude_linked_object_t *)ptr)->_list);
    
        if ( ptr->ident ) {
                prelude_string_destroy(ptr->ident);
                ptr->ident = NULL;
        }

        if ( ptr->interface ) {
                prelude_string_destroy(ptr->interface);
                ptr->interface = NULL;
        }

        if ( ptr->node ) {
                idmef_node_destroy(ptr->node);
                ptr->node = NULL;
        }

        if ( ptr->user ) {
                idmef_user_destroy(ptr->user);
                ptr->user = NULL;
        }

        if ( ptr->process ) {
                idmef_process_destroy(ptr->process);
                ptr->process = NULL;
        }

        if ( ptr->service ) {
                idmef_service_destroy(ptr->service);
                ptr->service = NULL;
        }

        {
                prelude_list_t *n, *tmp;
                idmef_file_t *entry;

                prelude_list_for_each_safe(&ptr->file_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        prelude_list_del_init(tmp);
                        idmef_file_destroy(entry);
                }
        }


        /* free() should be done by the caller */
}

/**
 * idmef_target_destroy:
 * @ptr: pointer to a #idmef_target_t object.
 *
 * Destroy @ptr and all of it's children.
 * The objects are only destroyed if their reference count reach zero.
 */

void idmef_target_destroy(idmef_target_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( --ptr->refcount )
                return;

        idmef_target_destroy_internal(ptr);
        free(ptr);
}

/**
 * idmef_target_get_ident:
 * @ptr: pointer to a #idmef_target_t object.
 *
 * Get ident children of the #idmef_target_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_target_get_ident(idmef_target_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->ident;
}

/**
 * idmef_target_set_ident:
 * @ptr: pointer to a #idmef_target_t object.
 * @ident: pointer to a #prelude_string_t object.
 *
 * Set @ident object as a children of @ptr.
 * if @ptr already contain an @ident object, then it is destroyed,
 * and updated to point to the provided @ident object.
 */

void idmef_target_set_ident(idmef_target_t *ptr, prelude_string_t *ident)
{
        prelude_return_if_fail(ptr);

        if ( ptr->ident )
                prelude_string_destroy(ptr->ident);

        ptr->ident = ident;
}

/**
 * idmef_target_new_ident:
 * @ptr: pointer to a #idmef_target_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new ident object, children of #idmef_target_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_target_new_ident(idmef_target_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->ident ) {
                retval = prelude_string_new(&ptr->ident);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->ident;
        return 0;
}

/**
 * idmef_target_get_decoy:
 * @ptr: pointer to a #idmef_target_t object.
 *
 * Get decoy children of the #idmef_target_t object.
 *
 * Returns: a pointer to a idmef_target_decoy_t object, or NULL if the children object is not set.
 */
idmef_target_decoy_t idmef_target_get_decoy(idmef_target_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->decoy;
}

/**
 * idmef_target_set_decoy:
 * @ptr: pointer to a #idmef_target_t object.
 * @decoy: pointer to a #idmef_target_decoy_t object.
 *
 * Set @decoy object as a children of @ptr.
 * if @ptr already contain an @decoy object, then it is destroyed,
 * and updated to point to the provided @decoy object.
 */

void idmef_target_set_decoy(idmef_target_t *ptr, idmef_target_decoy_t decoy)
{
        prelude_return_if_fail(ptr);
        ptr->decoy = decoy;
}

/**
 * idmef_target_new_decoy:
 * @ptr: pointer to a #idmef_target_t object.
 * @ret: pointer to an address where to store the created #idmef_target_decoy_t object.
 *
 * Create a new decoy object, children of #idmef_target_t.
 * If @ptr already contain a #idmef_target_decoy_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_target_new_decoy(idmef_target_t *ptr, idmef_target_decoy_t **ret)
{
        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        *ret = &ptr->decoy;
        return 0;
}

/**
 * idmef_target_get_interface:
 * @ptr: pointer to a #idmef_target_t object.
 *
 * Get interface children of the #idmef_target_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_target_get_interface(idmef_target_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->interface;
}

/**
 * idmef_target_set_interface:
 * @ptr: pointer to a #idmef_target_t object.
 * @interface: pointer to a #prelude_string_t object.
 *
 * Set @interface object as a children of @ptr.
 * if @ptr already contain an @interface object, then it is destroyed,
 * and updated to point to the provided @interface object.
 */

void idmef_target_set_interface(idmef_target_t *ptr, prelude_string_t *interface)
{
        prelude_return_if_fail(ptr);

        if ( ptr->interface )
                prelude_string_destroy(ptr->interface);

        ptr->interface = interface;
}

/**
 * idmef_target_new_interface:
 * @ptr: pointer to a #idmef_target_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new interface object, children of #idmef_target_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_target_new_interface(idmef_target_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->interface ) {
                retval = prelude_string_new(&ptr->interface);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->interface;
        return 0;
}

/**
 * idmef_target_get_node:
 * @ptr: pointer to a #idmef_target_t object.
 *
 * Get node children of the #idmef_target_t object.
 *
 * Returns: a pointer to a idmef_node_t object, or NULL if the children object is not set.
 */
idmef_node_t *idmef_target_get_node(idmef_target_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->node;
}

/**
 * idmef_target_set_node:
 * @ptr: pointer to a #idmef_target_t object.
 * @node: pointer to a #idmef_node_t object.
 *
 * Set @node object as a children of @ptr.
 * if @ptr already contain an @node object, then it is destroyed,
 * and updated to point to the provided @node object.
 */

void idmef_target_set_node(idmef_target_t *ptr, idmef_node_t *node)
{
        prelude_return_if_fail(ptr);

        if ( ptr->node )
                idmef_node_destroy(ptr->node);

        ptr->node = node;
}

/**
 * idmef_target_new_node:
 * @ptr: pointer to a #idmef_target_t object.
 * @ret: pointer to an address where to store the created #idmef_node_t object.
 *
 * Create a new node object, children of #idmef_target_t.
 * If @ptr already contain a #idmef_node_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_target_new_node(idmef_target_t *ptr, idmef_node_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->node ) {
                retval = idmef_node_new(&ptr->node);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->node;
        return 0;
}

/**
 * idmef_target_get_user:
 * @ptr: pointer to a #idmef_target_t object.
 *
 * Get user children of the #idmef_target_t object.
 *
 * Returns: a pointer to a idmef_user_t object, or NULL if the children object is not set.
 */
idmef_user_t *idmef_target_get_user(idmef_target_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->user;
}

/**
 * idmef_target_set_user:
 * @ptr: pointer to a #idmef_target_t object.
 * @user: pointer to a #idmef_user_t object.
 *
 * Set @user object as a children of @ptr.
 * if @ptr already contain an @user object, then it is destroyed,
 * and updated to point to the provided @user object.
 */

void idmef_target_set_user(idmef_target_t *ptr, idmef_user_t *user)
{
        prelude_return_if_fail(ptr);

        if ( ptr->user )
                idmef_user_destroy(ptr->user);

        ptr->user = user;
}

/**
 * idmef_target_new_user:
 * @ptr: pointer to a #idmef_target_t object.
 * @ret: pointer to an address where to store the created #idmef_user_t object.
 *
 * Create a new user object, children of #idmef_target_t.
 * If @ptr already contain a #idmef_user_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_target_new_user(idmef_target_t *ptr, idmef_user_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->user ) {
                retval = idmef_user_new(&ptr->user);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->user;
        return 0;
}

/**
 * idmef_target_get_process:
 * @ptr: pointer to a #idmef_target_t object.
 *
 * Get process children of the #idmef_target_t object.
 *
 * Returns: a pointer to a idmef_process_t object, or NULL if the children object is not set.
 */
idmef_process_t *idmef_target_get_process(idmef_target_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->process;
}

/**
 * idmef_target_set_process:
 * @ptr: pointer to a #idmef_target_t object.
 * @process: pointer to a #idmef_process_t object.
 *
 * Set @process object as a children of @ptr.
 * if @ptr already contain an @process object, then it is destroyed,
 * and updated to point to the provided @process object.
 */

void idmef_target_set_process(idmef_target_t *ptr, idmef_process_t *process)
{
        prelude_return_if_fail(ptr);

        if ( ptr->process )
                idmef_process_destroy(ptr->process);

        ptr->process = process;
}

/**
 * idmef_target_new_process:
 * @ptr: pointer to a #idmef_target_t object.
 * @ret: pointer to an address where to store the created #idmef_process_t object.
 *
 * Create a new process object, children of #idmef_target_t.
 * If @ptr already contain a #idmef_process_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_target_new_process(idmef_target_t *ptr, idmef_process_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->process ) {
                retval = idmef_process_new(&ptr->process);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->process;
        return 0;
}

/**
 * idmef_target_get_service:
 * @ptr: pointer to a #idmef_target_t object.
 *
 * Get service children of the #idmef_target_t object.
 *
 * Returns: a pointer to a idmef_service_t object, or NULL if the children object is not set.
 */
idmef_service_t *idmef_target_get_service(idmef_target_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->service;
}

/**
 * idmef_target_set_service:
 * @ptr: pointer to a #idmef_target_t object.
 * @service: pointer to a #idmef_service_t object.
 *
 * Set @service object as a children of @ptr.
 * if @ptr already contain an @service object, then it is destroyed,
 * and updated to point to the provided @service object.
 */

void idmef_target_set_service(idmef_target_t *ptr, idmef_service_t *service)
{
        prelude_return_if_fail(ptr);

        if ( ptr->service )
                idmef_service_destroy(ptr->service);

        ptr->service = service;
}

/**
 * idmef_target_new_service:
 * @ptr: pointer to a #idmef_target_t object.
 * @ret: pointer to an address where to store the created #idmef_service_t object.
 *
 * Create a new service object, children of #idmef_target_t.
 * If @ptr already contain a #idmef_service_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_target_new_service(idmef_target_t *ptr, idmef_service_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->service ) {
                retval = idmef_service_new(&ptr->service);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->service;
        return 0;
}

/**
 * idmef_target_get_next_file:
 * @target: pointer to a #idmef_target_t object.
 * @file_cur: pointer to a #idmef_file_t object.
 *
 * Get the next #idmef_file_t object listed in @ptr.
 * When iterating over the idmef_file_t object listed in @ptr,
 * @object should be set to the latest returned #idmef_file_t object.
 *
 * Returns: the next #idmef_file_t in the list.
 */
idmef_file_t *idmef_target_get_next_file(idmef_target_t *target, idmef_file_t *file_cur)
{
        prelude_list_t *tmp = (file_cur) ? &((prelude_linked_object_t *) file_cur)->_list : NULL;

        prelude_return_val_if_fail(target, NULL);

        prelude_list_for_each_continue(&target->file_list, tmp)
                return prelude_linked_object_get_object(tmp);

        return NULL;
}


/**
 * idmef_target_set_file:
 * @ptr: pointer to a #idmef_target_t object.
 * @object: pointer to a #idmef_file_t object.
 * @pos: Position in the list.
 *
 * Add @object to position @pos of @ptr list of #idmef_file_t object.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 */
void idmef_target_set_file(idmef_target_t *ptr, idmef_file_t *object, int pos)
{
        prelude_return_if_fail(ptr);
        prelude_return_if_fail(object);

        if ( ! prelude_list_is_empty(&((prelude_linked_object_t *) object)->_list) )
                prelude_list_del_init(&((prelude_linked_object_t *) object)->_list);

        list_insert(&ptr->file_list, &((prelude_linked_object_t *) object)->_list, pos);
}


/**
 * idmef_target_new_file:
 * @ptr: pointer to a #idmef_target_t object.
 * @ret: pointer to an address where to store the created #idmef_file_t object.
 * @pos: position in the list.
 *
 * Create a new #idmef_file_t children of @ptr, and add it to position @pos of
 * @ptr list of #idmef_file_t object. The created #idmef_file_t object is
 * stored in @ret.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_target_new_file(idmef_target_t *ptr, idmef_file_t **ret, int pos)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        retval = idmef_file_new(ret);
        if ( retval < 0 )
                return retval;

        list_insert(&ptr->file_list, &((prelude_linked_object_t *)(*ret))->_list, pos);

        return 0;
}


/**
 * idmef_target_copy:
 * @src: Source of the copy.
 * @dst: Where to copy the object.
 *
 * Copy a new #idmef_target_t object from @src to @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_target_copy(const idmef_target_t *src, idmef_target_t *dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));
        prelude_return_val_if_fail(dst, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = 0;

        if ( dst->ident ) {
                prelude_string_destroy(dst->ident);
                dst->ident = NULL;
        }

        if ( src->ident ) {
                ret = prelude_string_clone(src->ident, &dst->ident);
                if ( ret < 0 )
                        return ret;
        }

        dst->decoy = src->decoy;

        if ( dst->interface ) {
                prelude_string_destroy(dst->interface);
                dst->interface = NULL;
        }

        if ( src->interface ) {
                ret = prelude_string_clone(src->interface, &dst->interface);
                if ( ret < 0 )
                        return ret;
        }

        if ( dst->node ) {
                idmef_node_destroy(dst->node);
                dst->node = NULL;
        }

        if ( src->node ) {
                ret = idmef_node_clone(src->node, &dst->node);
                if ( ret < 0 )
                        return ret;
        }

        if ( dst->user ) {
                idmef_user_destroy(dst->user);
                dst->user = NULL;
        }

        if ( src->user ) {
                ret = idmef_user_clone(src->user, &dst->user);
                if ( ret < 0 )
                        return ret;
        }

        if ( dst->process ) {
                idmef_process_destroy(dst->process);
                dst->process = NULL;
        }

        if ( src->process ) {
                ret = idmef_process_clone(src->process, &dst->process);
                if ( ret < 0 )
                        return ret;
        }

        if ( dst->service ) {
                idmef_service_destroy(dst->service);
                dst->service = NULL;
        }

        if ( src->service ) {
                ret = idmef_service_clone(src->service, &dst->service);
                if ( ret < 0 )
                        return ret;
        }

        {
                prelude_list_t *n, *tmp;
                idmef_file_t *entry, *new;

                prelude_list_for_each_safe(&dst->file_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        idmef_file_destroy(entry);
                }

                prelude_list_for_each_safe(&src->file_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        idmef_file_clone(entry, &new);
                        prelude_list_add_tail(&dst->file_list, &((prelude_linked_object_t *) new)->_list);
                }
        }

        return 0;
}

/**
 * idmef_target_clone:
 * @src: Object to be cloned.
 * @dst: Address where to store the pointer to the cloned object.
 *
 * Create a copy of @src, and store it in @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_target_clone(idmef_target_t *src, idmef_target_t **dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = idmef_target_new(dst);
        if ( ret < 0 )
                return ret;

        return idmef_target_copy(src, *dst);
}

/**
 * idmef_target_compare:
 * @obj1: Object to compare with @obj2.
 * @obj2: Object to compare with @obj1.
 *
 * Compare @obj1 with @obj2.
 *
 * Returns: 0 on match, a negative value on comparison failure.
 */
int idmef_target_compare(const idmef_target_t *obj1, const idmef_target_t *obj2)
{
        int ret = 0;

        if ( obj1 == NULL && obj2 == NULL )
                return 0;

        else if ( obj1 == NULL || obj2 == NULL )
                return -1;

        ret = prelude_string_compare(obj1->ident, obj2->ident);
        if ( ret != 0 )
                return ret;

        if ( obj1->decoy != obj2->decoy )
                return -1;

        ret = prelude_string_compare(obj1->interface, obj2->interface);
        if ( ret != 0 )
                return ret;

        ret = idmef_node_compare(obj1->node, obj2->node);
        if ( ret != 0 )
                return ret;

        ret = idmef_user_compare(obj1->user, obj2->user);
        if ( ret != 0 )
                return ret;

        ret = idmef_process_compare(obj1->process, obj2->process);
        if ( ret != 0 )
                return ret;

        ret = idmef_service_compare(obj1->service, obj2->service);
        if ( ret != 0 )
                return ret;

        {
                prelude_list_t *tmp1, *tmp2;
                idmef_file_t *entry1, *entry2;

                tmp1 = tmp2 = NULL;
                do {
                        entry1 = entry2 = NULL;

                        prelude_list_for_each_continue(&obj1->file_list, tmp1) {
                                entry1 = prelude_linked_object_get_object(tmp1);
                                break;
                        }

                        prelude_list_for_each_continue(&obj2->file_list, tmp2) {
                                entry2 = prelude_linked_object_get_object(tmp2);
                                break;
                        }

                        ret = idmef_file_compare(entry1, entry2);
                        if ( ret != 0 )
                                return ret;

                } while ( entry1 && entry2 );
        }

        return ret;
}

/**
 * idmef_analyzer_new:
 * @ret: Pointer where to store the created #idmef_analyzer_t object.
 *
 * Create a new #idmef_analyzer_t object.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_analyzer_new(idmef_analyzer_t **ret)
{
        *ret = calloc(1, sizeof(**ret));
        if ( ! *ret )
                return prelude_error_from_errno(errno);

        (*ret)->_idmef_object_id = IDMEF_CLASS_ID_ANALYZER;

        prelude_list_init(&((prelude_linked_object_t *) (*ret))->_list);

        (*ret)->refcount = 1;

        return 0;

}

/**
 * idmef_analyzer_ref:
 * @analyzer: pointer to a #idmef_analyzer_t object.
 *
 * Increase @analyzer reference count, so that it can be referenced
 * multiple time.
 *
 * Returns: a pointer to @analyzer.
 */
idmef_analyzer_t *idmef_analyzer_ref(idmef_analyzer_t *analyzer)
{
        prelude_return_val_if_fail(analyzer, NULL);
        analyzer->refcount++;

        return analyzer;
}

int _idmef_analyzer_get_child(void *p, idmef_class_child_id_t child, void **childptr)
{
        idmef_analyzer_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));
        *childptr = NULL;

        switch ( child ) {

                case 0:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->analyzerid, TRUE);
                case 1:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->name, TRUE);
                case 2:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->manufacturer, TRUE);
                case 3:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->model, TRUE);
                case 4:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->version, TRUE);
                case 5:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->class, TRUE);
                case 6:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->ostype, TRUE);
                case 7:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->osversion, TRUE);
                case 8:
                        *childptr = ptr->node;
                        return 0;

                case 9:
                        *childptr = ptr->process;
                        return 0;

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_analyzer_new_child(void *p, idmef_class_child_id_t child, int n, void **ret)
{
        idmef_analyzer_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        return idmef_analyzer_new_analyzerid(ptr, (prelude_string_t **) ret);

                case 1:
                        return idmef_analyzer_new_name(ptr, (prelude_string_t **) ret);

                case 2:
                        return idmef_analyzer_new_manufacturer(ptr, (prelude_string_t **) ret);

                case 3:
                        return idmef_analyzer_new_model(ptr, (prelude_string_t **) ret);

                case 4:
                        return idmef_analyzer_new_version(ptr, (prelude_string_t **) ret);

                case 5:
                        return idmef_analyzer_new_class(ptr, (prelude_string_t **) ret);

                case 6:
                        return idmef_analyzer_new_ostype(ptr, (prelude_string_t **) ret);

                case 7:
                        return idmef_analyzer_new_osversion(ptr, (prelude_string_t **) ret);

                case 8:
                        return idmef_analyzer_new_node(ptr, (idmef_node_t **) ret);

                case 9:
                        return idmef_analyzer_new_process(ptr, (idmef_process_t **) ret);

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_analyzer_destroy_child(void *p, idmef_class_child_id_t child, int n)
{
        idmef_analyzer_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        if ( ptr->analyzerid ) {
                                prelude_string_destroy(ptr->analyzerid);
                                ptr->analyzerid = NULL;
                        }

                        return 0;

                case 1:
                        if ( ptr->name ) {
                                prelude_string_destroy(ptr->name);
                                ptr->name = NULL;
                        }

                        return 0;

                case 2:
                        if ( ptr->manufacturer ) {
                                prelude_string_destroy(ptr->manufacturer);
                                ptr->manufacturer = NULL;
                        }

                        return 0;

                case 3:
                        if ( ptr->model ) {
                                prelude_string_destroy(ptr->model);
                                ptr->model = NULL;
                        }

                        return 0;

                case 4:
                        if ( ptr->version ) {
                                prelude_string_destroy(ptr->version);
                                ptr->version = NULL;
                        }

                        return 0;

                case 5:
                        if ( ptr->class ) {
                                prelude_string_destroy(ptr->class);
                                ptr->class = NULL;
                        }

                        return 0;

                case 6:
                        if ( ptr->ostype ) {
                                prelude_string_destroy(ptr->ostype);
                                ptr->ostype = NULL;
                        }

                        return 0;

                case 7:
                        if ( ptr->osversion ) {
                                prelude_string_destroy(ptr->osversion);
                                ptr->osversion = NULL;
                        }

                        return 0;

                case 8:
                        if ( ptr->node ) {
                                idmef_node_destroy(ptr->node);
                                ptr->node = NULL;
                        }

                        return 0;

                case 9:
                        if ( ptr->process ) {
                                idmef_process_destroy(ptr->process);
                                ptr->process = NULL;
                        }

                        return 0;

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

static void idmef_analyzer_destroy_internal(idmef_analyzer_t *ptr)
{
        prelude_return_if_fail(ptr);

       if ( ! prelude_list_is_empty(&((prelude_linked_object_t *)ptr)->_list) )
               prelude_list_del_init(&((prelude_linked_object_t *)ptr)->_list);
    
        if ( ptr->analyzerid ) {
                prelude_string_destroy(ptr->analyzerid);
                ptr->analyzerid = NULL;
        }

        if ( ptr->name ) {
                prelude_string_destroy(ptr->name);
                ptr->name = NULL;
        }

        if ( ptr->manufacturer ) {
                prelude_string_destroy(ptr->manufacturer);
                ptr->manufacturer = NULL;
        }

        if ( ptr->model ) {
                prelude_string_destroy(ptr->model);
                ptr->model = NULL;
        }

        if ( ptr->version ) {
                prelude_string_destroy(ptr->version);
                ptr->version = NULL;
        }

        if ( ptr->class ) {
                prelude_string_destroy(ptr->class);
                ptr->class = NULL;
        }

        if ( ptr->ostype ) {
                prelude_string_destroy(ptr->ostype);
                ptr->ostype = NULL;
        }

        if ( ptr->osversion ) {
                prelude_string_destroy(ptr->osversion);
                ptr->osversion = NULL;
        }

        if ( ptr->node ) {
                idmef_node_destroy(ptr->node);
                ptr->node = NULL;
        }

        if ( ptr->process ) {
                idmef_process_destroy(ptr->process);
                ptr->process = NULL;
        }


        /* free() should be done by the caller */
}

/**
 * idmef_analyzer_destroy:
 * @ptr: pointer to a #idmef_analyzer_t object.
 *
 * Destroy @ptr and all of it's children.
 * The objects are only destroyed if their reference count reach zero.
 */

void idmef_analyzer_destroy(idmef_analyzer_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( --ptr->refcount )
                return;

        idmef_analyzer_destroy_internal(ptr);
        free(ptr);
}

/**
 * idmef_analyzer_get_analyzerid:
 * @ptr: pointer to a #idmef_analyzer_t object.
 *
 * Get analyzerid children of the #idmef_analyzer_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_analyzer_get_analyzerid(idmef_analyzer_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->analyzerid;
}

/**
 * idmef_analyzer_set_analyzerid:
 * @ptr: pointer to a #idmef_analyzer_t object.
 * @analyzerid: pointer to a #prelude_string_t object.
 *
 * Set @analyzerid object as a children of @ptr.
 * if @ptr already contain an @analyzerid object, then it is destroyed,
 * and updated to point to the provided @analyzerid object.
 */

void idmef_analyzer_set_analyzerid(idmef_analyzer_t *ptr, prelude_string_t *analyzerid)
{
        prelude_return_if_fail(ptr);

        if ( ptr->analyzerid )
                prelude_string_destroy(ptr->analyzerid);

        ptr->analyzerid = analyzerid;
}

/**
 * idmef_analyzer_new_analyzerid:
 * @ptr: pointer to a #idmef_analyzer_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new analyzerid object, children of #idmef_analyzer_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_analyzer_new_analyzerid(idmef_analyzer_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->analyzerid ) {
                retval = prelude_string_new(&ptr->analyzerid);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->analyzerid;
        return 0;
}

/**
 * idmef_analyzer_get_name:
 * @ptr: pointer to a #idmef_analyzer_t object.
 *
 * Get name children of the #idmef_analyzer_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_analyzer_get_name(idmef_analyzer_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->name;
}

/**
 * idmef_analyzer_set_name:
 * @ptr: pointer to a #idmef_analyzer_t object.
 * @name: pointer to a #prelude_string_t object.
 *
 * Set @name object as a children of @ptr.
 * if @ptr already contain an @name object, then it is destroyed,
 * and updated to point to the provided @name object.
 */

void idmef_analyzer_set_name(idmef_analyzer_t *ptr, prelude_string_t *name)
{
        prelude_return_if_fail(ptr);

        if ( ptr->name )
                prelude_string_destroy(ptr->name);

        ptr->name = name;
}

/**
 * idmef_analyzer_new_name:
 * @ptr: pointer to a #idmef_analyzer_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new name object, children of #idmef_analyzer_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_analyzer_new_name(idmef_analyzer_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->name ) {
                retval = prelude_string_new(&ptr->name);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->name;
        return 0;
}

/**
 * idmef_analyzer_get_manufacturer:
 * @ptr: pointer to a #idmef_analyzer_t object.
 *
 * Get manufacturer children of the #idmef_analyzer_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_analyzer_get_manufacturer(idmef_analyzer_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->manufacturer;
}

/**
 * idmef_analyzer_set_manufacturer:
 * @ptr: pointer to a #idmef_analyzer_t object.
 * @manufacturer: pointer to a #prelude_string_t object.
 *
 * Set @manufacturer object as a children of @ptr.
 * if @ptr already contain an @manufacturer object, then it is destroyed,
 * and updated to point to the provided @manufacturer object.
 */

void idmef_analyzer_set_manufacturer(idmef_analyzer_t *ptr, prelude_string_t *manufacturer)
{
        prelude_return_if_fail(ptr);

        if ( ptr->manufacturer )
                prelude_string_destroy(ptr->manufacturer);

        ptr->manufacturer = manufacturer;
}

/**
 * idmef_analyzer_new_manufacturer:
 * @ptr: pointer to a #idmef_analyzer_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new manufacturer object, children of #idmef_analyzer_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_analyzer_new_manufacturer(idmef_analyzer_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->manufacturer ) {
                retval = prelude_string_new(&ptr->manufacturer);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->manufacturer;
        return 0;
}

/**
 * idmef_analyzer_get_model:
 * @ptr: pointer to a #idmef_analyzer_t object.
 *
 * Get model children of the #idmef_analyzer_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_analyzer_get_model(idmef_analyzer_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->model;
}

/**
 * idmef_analyzer_set_model:
 * @ptr: pointer to a #idmef_analyzer_t object.
 * @model: pointer to a #prelude_string_t object.
 *
 * Set @model object as a children of @ptr.
 * if @ptr already contain an @model object, then it is destroyed,
 * and updated to point to the provided @model object.
 */

void idmef_analyzer_set_model(idmef_analyzer_t *ptr, prelude_string_t *model)
{
        prelude_return_if_fail(ptr);

        if ( ptr->model )
                prelude_string_destroy(ptr->model);

        ptr->model = model;
}

/**
 * idmef_analyzer_new_model:
 * @ptr: pointer to a #idmef_analyzer_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new model object, children of #idmef_analyzer_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_analyzer_new_model(idmef_analyzer_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->model ) {
                retval = prelude_string_new(&ptr->model);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->model;
        return 0;
}

/**
 * idmef_analyzer_get_version:
 * @ptr: pointer to a #idmef_analyzer_t object.
 *
 * Get version children of the #idmef_analyzer_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_analyzer_get_version(idmef_analyzer_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->version;
}

/**
 * idmef_analyzer_set_version:
 * @ptr: pointer to a #idmef_analyzer_t object.
 * @version: pointer to a #prelude_string_t object.
 *
 * Set @version object as a children of @ptr.
 * if @ptr already contain an @version object, then it is destroyed,
 * and updated to point to the provided @version object.
 */

void idmef_analyzer_set_version(idmef_analyzer_t *ptr, prelude_string_t *version)
{
        prelude_return_if_fail(ptr);

        if ( ptr->version )
                prelude_string_destroy(ptr->version);

        ptr->version = version;
}

/**
 * idmef_analyzer_new_version:
 * @ptr: pointer to a #idmef_analyzer_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new version object, children of #idmef_analyzer_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_analyzer_new_version(idmef_analyzer_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->version ) {
                retval = prelude_string_new(&ptr->version);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->version;
        return 0;
}

/**
 * idmef_analyzer_get_class:
 * @ptr: pointer to a #idmef_analyzer_t object.
 *
 * Get class children of the #idmef_analyzer_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_analyzer_get_class(idmef_analyzer_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->class;
}

/**
 * idmef_analyzer_set_class:
 * @ptr: pointer to a #idmef_analyzer_t object.
 * @class_str: pointer to a #prelude_string_t object.
 *
 * Set @class_str object as a children of @ptr.
 * if @ptr already contain an @class_str object, then it is destroyed,
 * and updated to point to the provided @class_str object.
 */

void idmef_analyzer_set_class(idmef_analyzer_t *ptr, prelude_string_t *class_str)
{
        prelude_return_if_fail(ptr);

        if ( ptr->class )
                prelude_string_destroy(ptr->class);

        ptr->class = class_str;
}

/**
 * idmef_analyzer_new_class:
 * @ptr: pointer to a #idmef_analyzer_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new class object, children of #idmef_analyzer_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_analyzer_new_class(idmef_analyzer_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->class ) {
                retval = prelude_string_new(&ptr->class);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->class;
        return 0;
}

/**
 * idmef_analyzer_get_ostype:
 * @ptr: pointer to a #idmef_analyzer_t object.
 *
 * Get ostype children of the #idmef_analyzer_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_analyzer_get_ostype(idmef_analyzer_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->ostype;
}

/**
 * idmef_analyzer_set_ostype:
 * @ptr: pointer to a #idmef_analyzer_t object.
 * @ostype: pointer to a #prelude_string_t object.
 *
 * Set @ostype object as a children of @ptr.
 * if @ptr already contain an @ostype object, then it is destroyed,
 * and updated to point to the provided @ostype object.
 */

void idmef_analyzer_set_ostype(idmef_analyzer_t *ptr, prelude_string_t *ostype)
{
        prelude_return_if_fail(ptr);

        if ( ptr->ostype )
                prelude_string_destroy(ptr->ostype);

        ptr->ostype = ostype;
}

/**
 * idmef_analyzer_new_ostype:
 * @ptr: pointer to a #idmef_analyzer_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new ostype object, children of #idmef_analyzer_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_analyzer_new_ostype(idmef_analyzer_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->ostype ) {
                retval = prelude_string_new(&ptr->ostype);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->ostype;
        return 0;
}

/**
 * idmef_analyzer_get_osversion:
 * @ptr: pointer to a #idmef_analyzer_t object.
 *
 * Get osversion children of the #idmef_analyzer_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_analyzer_get_osversion(idmef_analyzer_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->osversion;
}

/**
 * idmef_analyzer_set_osversion:
 * @ptr: pointer to a #idmef_analyzer_t object.
 * @osversion: pointer to a #prelude_string_t object.
 *
 * Set @osversion object as a children of @ptr.
 * if @ptr already contain an @osversion object, then it is destroyed,
 * and updated to point to the provided @osversion object.
 */

void idmef_analyzer_set_osversion(idmef_analyzer_t *ptr, prelude_string_t *osversion)
{
        prelude_return_if_fail(ptr);

        if ( ptr->osversion )
                prelude_string_destroy(ptr->osversion);

        ptr->osversion = osversion;
}

/**
 * idmef_analyzer_new_osversion:
 * @ptr: pointer to a #idmef_analyzer_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new osversion object, children of #idmef_analyzer_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_analyzer_new_osversion(idmef_analyzer_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->osversion ) {
                retval = prelude_string_new(&ptr->osversion);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->osversion;
        return 0;
}

/**
 * idmef_analyzer_get_node:
 * @ptr: pointer to a #idmef_analyzer_t object.
 *
 * Get node children of the #idmef_analyzer_t object.
 *
 * Returns: a pointer to a idmef_node_t object, or NULL if the children object is not set.
 */
idmef_node_t *idmef_analyzer_get_node(idmef_analyzer_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->node;
}

/**
 * idmef_analyzer_set_node:
 * @ptr: pointer to a #idmef_analyzer_t object.
 * @node: pointer to a #idmef_node_t object.
 *
 * Set @node object as a children of @ptr.
 * if @ptr already contain an @node object, then it is destroyed,
 * and updated to point to the provided @node object.
 */

void idmef_analyzer_set_node(idmef_analyzer_t *ptr, idmef_node_t *node)
{
        prelude_return_if_fail(ptr);

        if ( ptr->node )
                idmef_node_destroy(ptr->node);

        ptr->node = node;
}

/**
 * idmef_analyzer_new_node:
 * @ptr: pointer to a #idmef_analyzer_t object.
 * @ret: pointer to an address where to store the created #idmef_node_t object.
 *
 * Create a new node object, children of #idmef_analyzer_t.
 * If @ptr already contain a #idmef_node_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_analyzer_new_node(idmef_analyzer_t *ptr, idmef_node_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->node ) {
                retval = idmef_node_new(&ptr->node);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->node;
        return 0;
}

/**
 * idmef_analyzer_get_process:
 * @ptr: pointer to a #idmef_analyzer_t object.
 *
 * Get process children of the #idmef_analyzer_t object.
 *
 * Returns: a pointer to a idmef_process_t object, or NULL if the children object is not set.
 */
idmef_process_t *idmef_analyzer_get_process(idmef_analyzer_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->process;
}

/**
 * idmef_analyzer_set_process:
 * @ptr: pointer to a #idmef_analyzer_t object.
 * @process: pointer to a #idmef_process_t object.
 *
 * Set @process object as a children of @ptr.
 * if @ptr already contain an @process object, then it is destroyed,
 * and updated to point to the provided @process object.
 */

void idmef_analyzer_set_process(idmef_analyzer_t *ptr, idmef_process_t *process)
{
        prelude_return_if_fail(ptr);

        if ( ptr->process )
                idmef_process_destroy(ptr->process);

        ptr->process = process;
}

/**
 * idmef_analyzer_new_process:
 * @ptr: pointer to a #idmef_analyzer_t object.
 * @ret: pointer to an address where to store the created #idmef_process_t object.
 *
 * Create a new process object, children of #idmef_analyzer_t.
 * If @ptr already contain a #idmef_process_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_analyzer_new_process(idmef_analyzer_t *ptr, idmef_process_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->process ) {
                retval = idmef_process_new(&ptr->process);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->process;
        return 0;
}

/**
 * idmef_analyzer_copy:
 * @src: Source of the copy.
 * @dst: Where to copy the object.
 *
 * Copy a new #idmef_analyzer_t object from @src to @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_analyzer_copy(const idmef_analyzer_t *src, idmef_analyzer_t *dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));
        prelude_return_val_if_fail(dst, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = 0;

        if ( dst->analyzerid ) {
                prelude_string_destroy(dst->analyzerid);
                dst->analyzerid = NULL;
        }

        if ( src->analyzerid ) {
                ret = prelude_string_clone(src->analyzerid, &dst->analyzerid);
                if ( ret < 0 )
                        return ret;
        }

        if ( dst->name ) {
                prelude_string_destroy(dst->name);
                dst->name = NULL;
        }

        if ( src->name ) {
                ret = prelude_string_clone(src->name, &dst->name);
                if ( ret < 0 )
                        return ret;
        }

        if ( dst->manufacturer ) {
                prelude_string_destroy(dst->manufacturer);
                dst->manufacturer = NULL;
        }

        if ( src->manufacturer ) {
                ret = prelude_string_clone(src->manufacturer, &dst->manufacturer);
                if ( ret < 0 )
                        return ret;
        }

        if ( dst->model ) {
                prelude_string_destroy(dst->model);
                dst->model = NULL;
        }

        if ( src->model ) {
                ret = prelude_string_clone(src->model, &dst->model);
                if ( ret < 0 )
                        return ret;
        }

        if ( dst->version ) {
                prelude_string_destroy(dst->version);
                dst->version = NULL;
        }

        if ( src->version ) {
                ret = prelude_string_clone(src->version, &dst->version);
                if ( ret < 0 )
                        return ret;
        }

        if ( dst->class ) {
                prelude_string_destroy(dst->class);
                dst->class = NULL;
        }

        if ( src->class ) {
                ret = prelude_string_clone(src->class, &dst->class);
                if ( ret < 0 )
                        return ret;
        }

        if ( dst->ostype ) {
                prelude_string_destroy(dst->ostype);
                dst->ostype = NULL;
        }

        if ( src->ostype ) {
                ret = prelude_string_clone(src->ostype, &dst->ostype);
                if ( ret < 0 )
                        return ret;
        }

        if ( dst->osversion ) {
                prelude_string_destroy(dst->osversion);
                dst->osversion = NULL;
        }

        if ( src->osversion ) {
                ret = prelude_string_clone(src->osversion, &dst->osversion);
                if ( ret < 0 )
                        return ret;
        }

        if ( dst->node ) {
                idmef_node_destroy(dst->node);
                dst->node = NULL;
        }

        if ( src->node ) {
                ret = idmef_node_clone(src->node, &dst->node);
                if ( ret < 0 )
                        return ret;
        }

        if ( dst->process ) {
                idmef_process_destroy(dst->process);
                dst->process = NULL;
        }

        if ( src->process ) {
                ret = idmef_process_clone(src->process, &dst->process);
                if ( ret < 0 )
                        return ret;
        }

        return 0;
}

/**
 * idmef_analyzer_clone:
 * @src: Object to be cloned.
 * @dst: Address where to store the pointer to the cloned object.
 *
 * Create a copy of @src, and store it in @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_analyzer_clone(idmef_analyzer_t *src, idmef_analyzer_t **dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = idmef_analyzer_new(dst);
        if ( ret < 0 )
                return ret;

        return idmef_analyzer_copy(src, *dst);
}

/**
 * idmef_analyzer_compare:
 * @obj1: Object to compare with @obj2.
 * @obj2: Object to compare with @obj1.
 *
 * Compare @obj1 with @obj2.
 *
 * Returns: 0 on match, a negative value on comparison failure.
 */
int idmef_analyzer_compare(const idmef_analyzer_t *obj1, const idmef_analyzer_t *obj2)
{
        int ret = 0;

        if ( obj1 == NULL && obj2 == NULL )
                return 0;

        else if ( obj1 == NULL || obj2 == NULL )
                return -1;

        ret = prelude_string_compare(obj1->analyzerid, obj2->analyzerid);
        if ( ret != 0 )
                return ret;

        ret = prelude_string_compare(obj1->name, obj2->name);
        if ( ret != 0 )
                return ret;

        ret = prelude_string_compare(obj1->manufacturer, obj2->manufacturer);
        if ( ret != 0 )
                return ret;

        ret = prelude_string_compare(obj1->model, obj2->model);
        if ( ret != 0 )
                return ret;

        ret = prelude_string_compare(obj1->version, obj2->version);
        if ( ret != 0 )
                return ret;

        ret = prelude_string_compare(obj1->class, obj2->class);
        if ( ret != 0 )
                return ret;

        ret = prelude_string_compare(obj1->ostype, obj2->ostype);
        if ( ret != 0 )
                return ret;

        ret = prelude_string_compare(obj1->osversion, obj2->osversion);
        if ( ret != 0 )
                return ret;

        ret = idmef_node_compare(obj1->node, obj2->node);
        if ( ret != 0 )
                return ret;

        ret = idmef_process_compare(obj1->process, obj2->process);
        if ( ret != 0 )
                return ret;

        return ret;
}

/**
 * idmef_alertident_new:
 * @ret: Pointer where to store the created #idmef_alertident_t object.
 *
 * Create a new #idmef_alertident_t object.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_alertident_new(idmef_alertident_t **ret)
{
        *ret = calloc(1, sizeof(**ret));
        if ( ! *ret )
                return prelude_error_from_errno(errno);

        (*ret)->_idmef_object_id = IDMEF_CLASS_ID_ALERTIDENT;

        prelude_list_init(&((prelude_linked_object_t *) (*ret))->_list);

        (*ret)->refcount = 1;

        {
                int retval = prelude_string_new(&(*ret)->alertident);

                if ( retval < 0 ) {
                        idmef_alertident_destroy(*ret);
                        *ret = NULL;
                        return retval;
                }
        }

        return 0;

}

/**
 * idmef_alertident_ref:
 * @alertident: pointer to a #idmef_alertident_t object.
 *
 * Increase @alertident reference count, so that it can be referenced
 * multiple time.
 *
 * Returns: a pointer to @alertident.
 */
idmef_alertident_t *idmef_alertident_ref(idmef_alertident_t *alertident)
{
        prelude_return_val_if_fail(alertident, NULL);
        alertident->refcount++;

        return alertident;
}

int _idmef_alertident_get_child(void *p, idmef_class_child_id_t child, void **childptr)
{
        idmef_alertident_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));
        *childptr = NULL;

        switch ( child ) {

                case 0:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->alertident, TRUE);
                case 1:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->analyzerid, TRUE);
                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_alertident_new_child(void *p, idmef_class_child_id_t child, int n, void **ret)
{
        idmef_alertident_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        return idmef_alertident_new_alertident(ptr, (prelude_string_t **) ret);

                case 1:
                        return idmef_alertident_new_analyzerid(ptr, (prelude_string_t **) ret);

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_alertident_destroy_child(void *p, idmef_class_child_id_t child, int n)
{
        idmef_alertident_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        if ( ptr->alertident ) {
                                prelude_string_destroy(ptr->alertident);
                                ptr->alertident = NULL;
                        }

                        return 0;

                case 1:
                        if ( ptr->analyzerid ) {
                                prelude_string_destroy(ptr->analyzerid);
                                ptr->analyzerid = NULL;
                        }

                        return 0;

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

static void idmef_alertident_destroy_internal(idmef_alertident_t *ptr)
{
        prelude_return_if_fail(ptr);

       if ( ! prelude_list_is_empty(&((prelude_linked_object_t *)ptr)->_list) )
               prelude_list_del_init(&((prelude_linked_object_t *)ptr)->_list);
    
        if ( ptr->alertident ) {
                prelude_string_destroy(ptr->alertident);
                ptr->alertident = NULL;
        }

        if ( ptr->analyzerid ) {
                prelude_string_destroy(ptr->analyzerid);
                ptr->analyzerid = NULL;
        }


        /* free() should be done by the caller */
}

/**
 * idmef_alertident_destroy:
 * @ptr: pointer to a #idmef_alertident_t object.
 *
 * Destroy @ptr and all of it's children.
 * The objects are only destroyed if their reference count reach zero.
 */

void idmef_alertident_destroy(idmef_alertident_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( --ptr->refcount )
                return;

        idmef_alertident_destroy_internal(ptr);
        free(ptr);
}

/**
 * idmef_alertident_get_alertident:
 * @ptr: pointer to a #idmef_alertident_t object.
 *
 * Get alertident children of the #idmef_alertident_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_alertident_get_alertident(idmef_alertident_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->alertident;
}

/**
 * idmef_alertident_set_alertident:
 * @ptr: pointer to a #idmef_alertident_t object.
 * @alertident: pointer to a #prelude_string_t object.
 *
 * Set @alertident object as a children of @ptr.
 * if @ptr already contain an @alertident object, then it is destroyed,
 * and updated to point to the provided @alertident object.
 */

void idmef_alertident_set_alertident(idmef_alertident_t *ptr, prelude_string_t *alertident)
{
        prelude_return_if_fail(ptr);

        if ( ptr->alertident )
                prelude_string_destroy(ptr->alertident);

        ptr->alertident = alertident;
}

/**
 * idmef_alertident_new_alertident:
 * @ptr: pointer to a #idmef_alertident_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new alertident object, children of #idmef_alertident_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_alertident_new_alertident(idmef_alertident_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->alertident ) {
                retval = prelude_string_new(&ptr->alertident);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->alertident;
        return 0;
}

/**
 * idmef_alertident_get_analyzerid:
 * @ptr: pointer to a #idmef_alertident_t object.
 *
 * Get analyzerid children of the #idmef_alertident_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_alertident_get_analyzerid(idmef_alertident_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->analyzerid;
}

/**
 * idmef_alertident_set_analyzerid:
 * @ptr: pointer to a #idmef_alertident_t object.
 * @analyzerid: pointer to a #prelude_string_t object.
 *
 * Set @analyzerid object as a children of @ptr.
 * if @ptr already contain an @analyzerid object, then it is destroyed,
 * and updated to point to the provided @analyzerid object.
 */

void idmef_alertident_set_analyzerid(idmef_alertident_t *ptr, prelude_string_t *analyzerid)
{
        prelude_return_if_fail(ptr);

        if ( ptr->analyzerid )
                prelude_string_destroy(ptr->analyzerid);

        ptr->analyzerid = analyzerid;
}

/**
 * idmef_alertident_new_analyzerid:
 * @ptr: pointer to a #idmef_alertident_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new analyzerid object, children of #idmef_alertident_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_alertident_new_analyzerid(idmef_alertident_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->analyzerid ) {
                retval = prelude_string_new(&ptr->analyzerid);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->analyzerid;
        return 0;
}

/**
 * idmef_alertident_copy:
 * @src: Source of the copy.
 * @dst: Where to copy the object.
 *
 * Copy a new #idmef_alertident_t object from @src to @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_alertident_copy(const idmef_alertident_t *src, idmef_alertident_t *dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));
        prelude_return_val_if_fail(dst, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = 0;

        if ( src->alertident ) {
                ret = prelude_string_copy(src->alertident, dst->alertident);
                if ( ret < 0 )
                        return ret;
        }

        if ( dst->analyzerid ) {
                prelude_string_destroy(dst->analyzerid);
                dst->analyzerid = NULL;
        }

        if ( src->analyzerid ) {
                ret = prelude_string_clone(src->analyzerid, &dst->analyzerid);
                if ( ret < 0 )
                        return ret;
        }

        return 0;
}

/**
 * idmef_alertident_clone:
 * @src: Object to be cloned.
 * @dst: Address where to store the pointer to the cloned object.
 *
 * Create a copy of @src, and store it in @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_alertident_clone(idmef_alertident_t *src, idmef_alertident_t **dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = idmef_alertident_new(dst);
        if ( ret < 0 )
                return ret;

        return idmef_alertident_copy(src, *dst);
}

/**
 * idmef_alertident_compare:
 * @obj1: Object to compare with @obj2.
 * @obj2: Object to compare with @obj1.
 *
 * Compare @obj1 with @obj2.
 *
 * Returns: 0 on match, a negative value on comparison failure.
 */
int idmef_alertident_compare(const idmef_alertident_t *obj1, const idmef_alertident_t *obj2)
{
        int ret = 0;

        if ( obj1 == NULL && obj2 == NULL )
                return 0;

        else if ( obj1 == NULL || obj2 == NULL )
                return -1;

        ret = prelude_string_compare(obj1->alertident, obj2->alertident);
        if ( ret != 0 )
                return ret;

        ret = prelude_string_compare(obj1->analyzerid, obj2->analyzerid);
        if ( ret != 0 )
                return ret;

        return ret;
}

/**
 * idmef_impact_new:
 * @ret: Pointer where to store the created #idmef_impact_t object.
 *
 * Create a new #idmef_impact_t object.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_impact_new(idmef_impact_t **ret)
{
        *ret = calloc(1, sizeof(**ret));
        if ( ! *ret )
                return prelude_error_from_errno(errno);

        (*ret)->_idmef_object_id = IDMEF_CLASS_ID_IMPACT;

        (*ret)->refcount = 1;

        return 0;

}

/**
 * idmef_impact_ref:
 * @impact: pointer to a #idmef_impact_t object.
 *
 * Increase @impact reference count, so that it can be referenced
 * multiple time.
 *
 * Returns: a pointer to @impact.
 */
idmef_impact_t *idmef_impact_ref(idmef_impact_t *impact)
{
        prelude_return_val_if_fail(impact, NULL);
        impact->refcount++;

        return impact;
}

int _idmef_impact_get_child(void *p, idmef_class_child_id_t child, void **childptr)
{
        idmef_impact_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));
        *childptr = NULL;

        switch ( child ) {

                case 0:
                       if ( ! ptr->severity_is_set )
                               return 0;
                       return idmef_value_new_enum_from_numeric((idmef_value_t **) childptr,
                                                                IDMEF_CLASS_ID_IMPACT_SEVERITY, ptr->severity);

                case 1:
                       if ( ! ptr->completion_is_set )
                               return 0;
                       return idmef_value_new_enum_from_numeric((idmef_value_t **) childptr,
                                                                IDMEF_CLASS_ID_IMPACT_COMPLETION, ptr->completion);

                case 2:
                       return idmef_value_new_enum_from_numeric((idmef_value_t **) childptr,
                                                                IDMEF_CLASS_ID_IMPACT_TYPE, ptr->type);

                case 3:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->description, TRUE);
                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_impact_new_child(void *p, idmef_class_child_id_t child, int n, void **ret)
{
        idmef_impact_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        return idmef_impact_new_severity(ptr, (idmef_impact_severity_t **) ret);

                case 1:
                        return idmef_impact_new_completion(ptr, (idmef_impact_completion_t **) ret);

                case 2:
                        return idmef_impact_new_type(ptr, (idmef_impact_type_t **) ret);

                case 3:
                        return idmef_impact_new_description(ptr, (prelude_string_t **) ret);

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_impact_destroy_child(void *p, idmef_class_child_id_t child, int n)
{
        idmef_impact_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        ptr->severity_is_set = 0;
                        return 0;

                case 1:
                        ptr->completion_is_set = 0;
                        return 0;

                case 2:
                        ptr->type = 0;
                        return 0;

                case 3:
                        if ( ptr->description ) {
                                prelude_string_destroy(ptr->description);
                                ptr->description = NULL;
                        }

                        return 0;

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

static void idmef_impact_destroy_internal(idmef_impact_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( ptr->description ) {
                prelude_string_destroy(ptr->description);
                ptr->description = NULL;
        }


        /* free() should be done by the caller */
}

/**
 * idmef_impact_destroy:
 * @ptr: pointer to a #idmef_impact_t object.
 *
 * Destroy @ptr and all of it's children.
 * The objects are only destroyed if their reference count reach zero.
 */

void idmef_impact_destroy(idmef_impact_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( --ptr->refcount )
                return;

        idmef_impact_destroy_internal(ptr);
        free(ptr);
}

/**
 * idmef_impact_get_severity:
 * @ptr: pointer to a #idmef_impact_t object.
 *
 * Get severity children of the #idmef_impact_t object.
 *
 * Returns: a pointer to a idmef_impact_severity_t object, or NULL if the children object is not set.
 */
idmef_impact_severity_t *idmef_impact_get_severity(idmef_impact_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->severity_is_set ? &ptr->severity : NULL;
}

/**
 * idmef_impact_set_severity:
 * @ptr: pointer to a #idmef_impact_t object.
 * @severity: pointer to a #idmef_impact_severity_t object.
 *
 * Set @severity object as a children of @ptr.
 * if @ptr already contain an @severity object, then it is destroyed,
 * and updated to point to the provided @severity object.
 */

void idmef_impact_set_severity(idmef_impact_t *ptr, idmef_impact_severity_t severity)
{
        prelude_return_if_fail(ptr);
        ptr->severity = severity;
        ptr->severity_is_set = 1;
}


void idmef_impact_unset_severity(idmef_impact_t *ptr)
{
        prelude_return_if_fail(ptr);
        ptr->severity_is_set = 0;
}


/**
 * idmef_impact_new_severity:
 * @ptr: pointer to a #idmef_impact_t object.
 * @ret: pointer to an address where to store the created #idmef_impact_severity_t object.
 *
 * Create a new severity object, children of #idmef_impact_t.
 * If @ptr already contain a #idmef_impact_severity_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_impact_new_severity(idmef_impact_t *ptr, idmef_impact_severity_t **ret)
{
        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));
        ptr->severity_is_set = 1;

        *ret = &ptr->severity;
        return 0;
}

/**
 * idmef_impact_get_completion:
 * @ptr: pointer to a #idmef_impact_t object.
 *
 * Get completion children of the #idmef_impact_t object.
 *
 * Returns: a pointer to a idmef_impact_completion_t object, or NULL if the children object is not set.
 */
idmef_impact_completion_t *idmef_impact_get_completion(idmef_impact_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->completion_is_set ? &ptr->completion : NULL;
}

/**
 * idmef_impact_set_completion:
 * @ptr: pointer to a #idmef_impact_t object.
 * @completion: pointer to a #idmef_impact_completion_t object.
 *
 * Set @completion object as a children of @ptr.
 * if @ptr already contain an @completion object, then it is destroyed,
 * and updated to point to the provided @completion object.
 */

void idmef_impact_set_completion(idmef_impact_t *ptr, idmef_impact_completion_t completion)
{
        prelude_return_if_fail(ptr);
        ptr->completion = completion;
        ptr->completion_is_set = 1;
}


void idmef_impact_unset_completion(idmef_impact_t *ptr)
{
        prelude_return_if_fail(ptr);
        ptr->completion_is_set = 0;
}


/**
 * idmef_impact_new_completion:
 * @ptr: pointer to a #idmef_impact_t object.
 * @ret: pointer to an address where to store the created #idmef_impact_completion_t object.
 *
 * Create a new completion object, children of #idmef_impact_t.
 * If @ptr already contain a #idmef_impact_completion_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_impact_new_completion(idmef_impact_t *ptr, idmef_impact_completion_t **ret)
{
        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));
        ptr->completion_is_set = 1;

        *ret = &ptr->completion;
        return 0;
}

/**
 * idmef_impact_get_type:
 * @ptr: pointer to a #idmef_impact_t object.
 *
 * Get type children of the #idmef_impact_t object.
 *
 * Returns: a pointer to a idmef_impact_type_t object, or NULL if the children object is not set.
 */
idmef_impact_type_t idmef_impact_get_type(idmef_impact_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->type;
}

/**
 * idmef_impact_set_type:
 * @ptr: pointer to a #idmef_impact_t object.
 * @type: pointer to a #idmef_impact_type_t object.
 *
 * Set @type object as a children of @ptr.
 * if @ptr already contain an @type object, then it is destroyed,
 * and updated to point to the provided @type object.
 */

void idmef_impact_set_type(idmef_impact_t *ptr, idmef_impact_type_t type)
{
        prelude_return_if_fail(ptr);
        ptr->type = type;
}

/**
 * idmef_impact_new_type:
 * @ptr: pointer to a #idmef_impact_t object.
 * @ret: pointer to an address where to store the created #idmef_impact_type_t object.
 *
 * Create a new type object, children of #idmef_impact_t.
 * If @ptr already contain a #idmef_impact_type_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_impact_new_type(idmef_impact_t *ptr, idmef_impact_type_t **ret)
{
        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        *ret = &ptr->type;
        return 0;
}

/**
 * idmef_impact_get_description:
 * @ptr: pointer to a #idmef_impact_t object.
 *
 * Get description children of the #idmef_impact_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_impact_get_description(idmef_impact_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->description;
}

/**
 * idmef_impact_set_description:
 * @ptr: pointer to a #idmef_impact_t object.
 * @description: pointer to a #prelude_string_t object.
 *
 * Set @description object as a children of @ptr.
 * if @ptr already contain an @description object, then it is destroyed,
 * and updated to point to the provided @description object.
 */

void idmef_impact_set_description(idmef_impact_t *ptr, prelude_string_t *description)
{
        prelude_return_if_fail(ptr);

        if ( ptr->description )
                prelude_string_destroy(ptr->description);

        ptr->description = description;
}

/**
 * idmef_impact_new_description:
 * @ptr: pointer to a #idmef_impact_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new description object, children of #idmef_impact_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_impact_new_description(idmef_impact_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->description ) {
                retval = prelude_string_new(&ptr->description);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->description;
        return 0;
}

/**
 * idmef_impact_copy:
 * @src: Source of the copy.
 * @dst: Where to copy the object.
 *
 * Copy a new #idmef_impact_t object from @src to @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_impact_copy(const idmef_impact_t *src, idmef_impact_t *dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));
        prelude_return_val_if_fail(dst, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = 0;

        dst->severity_is_set = src->severity_is_set;

        dst->severity = src->severity;

        dst->completion_is_set = src->completion_is_set;

        dst->completion = src->completion;

        dst->type = src->type;

        if ( dst->description ) {
                prelude_string_destroy(dst->description);
                dst->description = NULL;
        }

        if ( src->description ) {
                ret = prelude_string_clone(src->description, &dst->description);
                if ( ret < 0 )
                        return ret;
        }

        return 0;
}

/**
 * idmef_impact_clone:
 * @src: Object to be cloned.
 * @dst: Address where to store the pointer to the cloned object.
 *
 * Create a copy of @src, and store it in @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_impact_clone(idmef_impact_t *src, idmef_impact_t **dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = idmef_impact_new(dst);
        if ( ret < 0 )
                return ret;

        return idmef_impact_copy(src, *dst);
}

/**
 * idmef_impact_compare:
 * @obj1: Object to compare with @obj2.
 * @obj2: Object to compare with @obj1.
 *
 * Compare @obj1 with @obj2.
 *
 * Returns: 0 on match, a negative value on comparison failure.
 */
int idmef_impact_compare(const idmef_impact_t *obj1, const idmef_impact_t *obj2)
{
        int ret = 0;

        if ( obj1 == NULL && obj2 == NULL )
                return 0;

        else if ( obj1 == NULL || obj2 == NULL )
                return -1;

        if ( obj1->severity_is_set != obj2->severity_is_set )
                return -1;

        if ( obj1->severity_is_set && obj1->severity != obj2->severity )
                return -1;

        if ( obj1->completion_is_set != obj2->completion_is_set )
                return -1;

        if ( obj1->completion_is_set && obj1->completion != obj2->completion )
                return -1;

        if ( obj1->type != obj2->type )
                return -1;

        ret = prelude_string_compare(obj1->description, obj2->description);
        if ( ret != 0 )
                return ret;

        return ret;
}

/**
 * idmef_action_new:
 * @ret: Pointer where to store the created #idmef_action_t object.
 *
 * Create a new #idmef_action_t object.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_action_new(idmef_action_t **ret)
{
        *ret = calloc(1, sizeof(**ret));
        if ( ! *ret )
                return prelude_error_from_errno(errno);

        (*ret)->_idmef_object_id = IDMEF_CLASS_ID_ACTION;

        prelude_list_init(&((prelude_linked_object_t *) (*ret))->_list);

        (*ret)->refcount = 1;

        return 0;

}

/**
 * idmef_action_ref:
 * @action: pointer to a #idmef_action_t object.
 *
 * Increase @action reference count, so that it can be referenced
 * multiple time.
 *
 * Returns: a pointer to @action.
 */
idmef_action_t *idmef_action_ref(idmef_action_t *action)
{
        prelude_return_val_if_fail(action, NULL);
        action->refcount++;

        return action;
}

int _idmef_action_get_child(void *p, idmef_class_child_id_t child, void **childptr)
{
        idmef_action_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));
        *childptr = NULL;

        switch ( child ) {

                case 0:
                       return idmef_value_new_enum_from_numeric((idmef_value_t **) childptr,
                                                                IDMEF_CLASS_ID_ACTION_CATEGORY, ptr->category);

                case 1:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->description, TRUE);
                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_action_new_child(void *p, idmef_class_child_id_t child, int n, void **ret)
{
        idmef_action_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        return idmef_action_new_category(ptr, (idmef_action_category_t **) ret);

                case 1:
                        return idmef_action_new_description(ptr, (prelude_string_t **) ret);

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_action_destroy_child(void *p, idmef_class_child_id_t child, int n)
{
        idmef_action_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        ptr->category = 0;
                        return 0;

                case 1:
                        if ( ptr->description ) {
                                prelude_string_destroy(ptr->description);
                                ptr->description = NULL;
                        }

                        return 0;

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

static void idmef_action_destroy_internal(idmef_action_t *ptr)
{
        prelude_return_if_fail(ptr);

       if ( ! prelude_list_is_empty(&((prelude_linked_object_t *)ptr)->_list) )
               prelude_list_del_init(&((prelude_linked_object_t *)ptr)->_list);
    
        if ( ptr->description ) {
                prelude_string_destroy(ptr->description);
                ptr->description = NULL;
        }


        /* free() should be done by the caller */
}

/**
 * idmef_action_destroy:
 * @ptr: pointer to a #idmef_action_t object.
 *
 * Destroy @ptr and all of it's children.
 * The objects are only destroyed if their reference count reach zero.
 */

void idmef_action_destroy(idmef_action_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( --ptr->refcount )
                return;

        idmef_action_destroy_internal(ptr);
        free(ptr);
}

/**
 * idmef_action_get_category:
 * @ptr: pointer to a #idmef_action_t object.
 *
 * Get category children of the #idmef_action_t object.
 *
 * Returns: a pointer to a idmef_action_category_t object, or NULL if the children object is not set.
 */
idmef_action_category_t idmef_action_get_category(idmef_action_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->category;
}

/**
 * idmef_action_set_category:
 * @ptr: pointer to a #idmef_action_t object.
 * @category: pointer to a #idmef_action_category_t object.
 *
 * Set @category object as a children of @ptr.
 * if @ptr already contain an @category object, then it is destroyed,
 * and updated to point to the provided @category object.
 */

void idmef_action_set_category(idmef_action_t *ptr, idmef_action_category_t category)
{
        prelude_return_if_fail(ptr);
        ptr->category = category;
}

/**
 * idmef_action_new_category:
 * @ptr: pointer to a #idmef_action_t object.
 * @ret: pointer to an address where to store the created #idmef_action_category_t object.
 *
 * Create a new category object, children of #idmef_action_t.
 * If @ptr already contain a #idmef_action_category_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_action_new_category(idmef_action_t *ptr, idmef_action_category_t **ret)
{
        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        *ret = &ptr->category;
        return 0;
}

/**
 * idmef_action_get_description:
 * @ptr: pointer to a #idmef_action_t object.
 *
 * Get description children of the #idmef_action_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_action_get_description(idmef_action_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->description;
}

/**
 * idmef_action_set_description:
 * @ptr: pointer to a #idmef_action_t object.
 * @description: pointer to a #prelude_string_t object.
 *
 * Set @description object as a children of @ptr.
 * if @ptr already contain an @description object, then it is destroyed,
 * and updated to point to the provided @description object.
 */

void idmef_action_set_description(idmef_action_t *ptr, prelude_string_t *description)
{
        prelude_return_if_fail(ptr);

        if ( ptr->description )
                prelude_string_destroy(ptr->description);

        ptr->description = description;
}

/**
 * idmef_action_new_description:
 * @ptr: pointer to a #idmef_action_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new description object, children of #idmef_action_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_action_new_description(idmef_action_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->description ) {
                retval = prelude_string_new(&ptr->description);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->description;
        return 0;
}

/**
 * idmef_action_copy:
 * @src: Source of the copy.
 * @dst: Where to copy the object.
 *
 * Copy a new #idmef_action_t object from @src to @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_action_copy(const idmef_action_t *src, idmef_action_t *dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));
        prelude_return_val_if_fail(dst, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = 0;

        dst->category = src->category;

        if ( dst->description ) {
                prelude_string_destroy(dst->description);
                dst->description = NULL;
        }

        if ( src->description ) {
                ret = prelude_string_clone(src->description, &dst->description);
                if ( ret < 0 )
                        return ret;
        }

        return 0;
}

/**
 * idmef_action_clone:
 * @src: Object to be cloned.
 * @dst: Address where to store the pointer to the cloned object.
 *
 * Create a copy of @src, and store it in @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_action_clone(idmef_action_t *src, idmef_action_t **dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = idmef_action_new(dst);
        if ( ret < 0 )
                return ret;

        return idmef_action_copy(src, *dst);
}

/**
 * idmef_action_compare:
 * @obj1: Object to compare with @obj2.
 * @obj2: Object to compare with @obj1.
 *
 * Compare @obj1 with @obj2.
 *
 * Returns: 0 on match, a negative value on comparison failure.
 */
int idmef_action_compare(const idmef_action_t *obj1, const idmef_action_t *obj2)
{
        int ret = 0;

        if ( obj1 == NULL && obj2 == NULL )
                return 0;

        else if ( obj1 == NULL || obj2 == NULL )
                return -1;

        if ( obj1->category != obj2->category )
                return -1;

        ret = prelude_string_compare(obj1->description, obj2->description);
        if ( ret != 0 )
                return ret;

        return ret;
}

/**
 * idmef_confidence_new:
 * @ret: Pointer where to store the created #idmef_confidence_t object.
 *
 * Create a new #idmef_confidence_t object.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_confidence_new(idmef_confidence_t **ret)
{
        *ret = calloc(1, sizeof(**ret));
        if ( ! *ret )
                return prelude_error_from_errno(errno);

        (*ret)->_idmef_object_id = IDMEF_CLASS_ID_CONFIDENCE;

        (*ret)->refcount = 1;

        return 0;

}

/**
 * idmef_confidence_ref:
 * @confidence: pointer to a #idmef_confidence_t object.
 *
 * Increase @confidence reference count, so that it can be referenced
 * multiple time.
 *
 * Returns: a pointer to @confidence.
 */
idmef_confidence_t *idmef_confidence_ref(idmef_confidence_t *confidence)
{
        prelude_return_val_if_fail(confidence, NULL);
        confidence->refcount++;

        return confidence;
}

int _idmef_confidence_get_child(void *p, idmef_class_child_id_t child, void **childptr)
{
        idmef_confidence_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));
        *childptr = NULL;

        switch ( child ) {

                case 0:
                       return idmef_value_new_enum_from_numeric((idmef_value_t **) childptr,
                                                                IDMEF_CLASS_ID_CONFIDENCE_RATING, ptr->rating);

                case 1:
                       return idmef_value_new_float((idmef_value_t **) childptr, ptr->confidence);
                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_confidence_new_child(void *p, idmef_class_child_id_t child, int n, void **ret)
{
        idmef_confidence_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        return idmef_confidence_new_rating(ptr, (idmef_confidence_rating_t **) ret);

                case 1:
                        return idmef_confidence_new_confidence(ptr, (float **) ret);

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_confidence_destroy_child(void *p, idmef_class_child_id_t child, int n)
{
        idmef_confidence_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        ptr->rating = 0;
                        return 0;

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

static void idmef_confidence_destroy_internal(idmef_confidence_t *ptr)
{
        prelude_return_if_fail(ptr);


        /* free() should be done by the caller */
}

/**
 * idmef_confidence_destroy:
 * @ptr: pointer to a #idmef_confidence_t object.
 *
 * Destroy @ptr and all of it's children.
 * The objects are only destroyed if their reference count reach zero.
 */

void idmef_confidence_destroy(idmef_confidence_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( --ptr->refcount )
                return;

        idmef_confidence_destroy_internal(ptr);
        free(ptr);
}

/**
 * idmef_confidence_get_rating:
 * @ptr: pointer to a #idmef_confidence_t object.
 *
 * Get rating children of the #idmef_confidence_t object.
 *
 * Returns: a pointer to a idmef_confidence_rating_t object, or NULL if the children object is not set.
 */
idmef_confidence_rating_t idmef_confidence_get_rating(idmef_confidence_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->rating;
}

/**
 * idmef_confidence_set_rating:
 * @ptr: pointer to a #idmef_confidence_t object.
 * @rating: pointer to a #idmef_confidence_rating_t object.
 *
 * Set @rating object as a children of @ptr.
 * if @ptr already contain an @rating object, then it is destroyed,
 * and updated to point to the provided @rating object.
 */

void idmef_confidence_set_rating(idmef_confidence_t *ptr, idmef_confidence_rating_t rating)
{
        prelude_return_if_fail(ptr);
        ptr->rating = rating;
}

/**
 * idmef_confidence_new_rating:
 * @ptr: pointer to a #idmef_confidence_t object.
 * @ret: pointer to an address where to store the created #idmef_confidence_rating_t object.
 *
 * Create a new rating object, children of #idmef_confidence_t.
 * If @ptr already contain a #idmef_confidence_rating_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_confidence_new_rating(idmef_confidence_t *ptr, idmef_confidence_rating_t **ret)
{
        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        *ret = &ptr->rating;
        return 0;
}

/**
 * idmef_confidence_get_confidence:
 * @ptr: pointer to a #idmef_confidence_t object.
 *
 * Get confidence children of the #idmef_confidence_t object.
 *
 * Returns: a pointer to a float object, or NULL if the children object is not set.
 */
float idmef_confidence_get_confidence(idmef_confidence_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->confidence;
}

/**
 * idmef_confidence_set_confidence:
 * @ptr: pointer to a #idmef_confidence_t object.
 * @confidence: pointer to a #float object.
 *
 * Set @confidence object as a children of @ptr.
 * if @ptr already contain an @confidence object, then it is destroyed,
 * and updated to point to the provided @confidence object.
 */

void idmef_confidence_set_confidence(idmef_confidence_t *ptr, float confidence)
{
        prelude_return_if_fail(ptr);
        ptr->confidence = confidence;
}

/**
 * idmef_confidence_new_confidence:
 * @ptr: pointer to a #idmef_confidence_t object.
 * @ret: pointer to an address where to store the created #float object.
 *
 * Create a new confidence object, children of #idmef_confidence_t.
 * If @ptr already contain a #float object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_confidence_new_confidence(idmef_confidence_t *ptr, float **ret)
{
        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        *ret = &ptr->confidence;
        return 0;
}

/**
 * idmef_confidence_copy:
 * @src: Source of the copy.
 * @dst: Where to copy the object.
 *
 * Copy a new #idmef_confidence_t object from @src to @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_confidence_copy(const idmef_confidence_t *src, idmef_confidence_t *dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));
        prelude_return_val_if_fail(dst, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = 0;

        dst->rating = src->rating;

        dst->confidence = src->confidence;

        return 0;
}

/**
 * idmef_confidence_clone:
 * @src: Object to be cloned.
 * @dst: Address where to store the pointer to the cloned object.
 *
 * Create a copy of @src, and store it in @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_confidence_clone(idmef_confidence_t *src, idmef_confidence_t **dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = idmef_confidence_new(dst);
        if ( ret < 0 )
                return ret;

        return idmef_confidence_copy(src, *dst);
}

/**
 * idmef_confidence_compare:
 * @obj1: Object to compare with @obj2.
 * @obj2: Object to compare with @obj1.
 *
 * Compare @obj1 with @obj2.
 *
 * Returns: 0 on match, a negative value on comparison failure.
 */
int idmef_confidence_compare(const idmef_confidence_t *obj1, const idmef_confidence_t *obj2)
{
        int ret = 0;

        if ( obj1 == NULL && obj2 == NULL )
                return 0;

        else if ( obj1 == NULL || obj2 == NULL )
                return -1;

        if ( obj1->rating != obj2->rating )
                return -1;

        ret = float_compare(obj1->confidence, obj2->confidence);

        return ret;
}

/**
 * idmef_assessment_new:
 * @ret: Pointer where to store the created #idmef_assessment_t object.
 *
 * Create a new #idmef_assessment_t object.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_assessment_new(idmef_assessment_t **ret)
{
        *ret = calloc(1, sizeof(**ret));
        if ( ! *ret )
                return prelude_error_from_errno(errno);

        (*ret)->_idmef_object_id = IDMEF_CLASS_ID_ASSESSMENT;

        (*ret)->refcount = 1;

        prelude_list_init(&(*ret)->action_list);


        return 0;

}

/**
 * idmef_assessment_ref:
 * @assessment: pointer to a #idmef_assessment_t object.
 *
 * Increase @assessment reference count, so that it can be referenced
 * multiple time.
 *
 * Returns: a pointer to @assessment.
 */
idmef_assessment_t *idmef_assessment_ref(idmef_assessment_t *assessment)
{
        prelude_return_val_if_fail(assessment, NULL);
        assessment->refcount++;

        return assessment;
}

int _idmef_assessment_get_child(void *p, idmef_class_child_id_t child, void **childptr)
{
        idmef_assessment_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));
        *childptr = NULL;

        switch ( child ) {

                case 0:
                        *childptr = ptr->impact;
                        return 0;

                case 1:
                        *childptr = &ptr->action_list;
                        return 0;

                case 2:
                        *childptr = ptr->confidence;
                        return 0;

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_assessment_new_child(void *p, idmef_class_child_id_t child, int n, void **ret)
{
        idmef_assessment_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        return idmef_assessment_new_impact(ptr, (idmef_impact_t **) ret);

                case 1: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n == IDMEF_LIST_APPEND || n == IDMEF_LIST_PREPEND )
                               return idmef_assessment_new_action(ptr, (idmef_action_t **) ret, n);

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->action_list, tmp) {
                                       if ( i++ == n ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->action_list, tmp) {
                                       if ( i++ == pos ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }

                        return idmef_assessment_new_action(ptr, (idmef_action_t **) ret, n);
                }

                case 2:
                        return idmef_assessment_new_confidence(ptr, (idmef_confidence_t **) ret);

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_assessment_destroy_child(void *p, idmef_class_child_id_t child, int n)
{
        idmef_assessment_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        if ( ptr->impact ) {
                                idmef_impact_destroy(ptr->impact);
                                ptr->impact = NULL;
                        }

                        return 0;

                case 1: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->action_list, tmp) {
                                       if ( i++ == n ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               idmef_action_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->action_list, tmp) {
                                       if ( i++ == pos ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               idmef_action_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }
                }

                case 2:
                        if ( ptr->confidence ) {
                                idmef_confidence_destroy(ptr->confidence);
                                ptr->confidence = NULL;
                        }

                        return 0;

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

static void idmef_assessment_destroy_internal(idmef_assessment_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( ptr->impact ) {
                idmef_impact_destroy(ptr->impact);
                ptr->impact = NULL;
        }

        {
                prelude_list_t *n, *tmp;
                idmef_action_t *entry;

                prelude_list_for_each_safe(&ptr->action_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        prelude_list_del_init(tmp);
                        idmef_action_destroy(entry);
                }
        }

        if ( ptr->confidence ) {
                idmef_confidence_destroy(ptr->confidence);
                ptr->confidence = NULL;
        }


        /* free() should be done by the caller */
}

/**
 * idmef_assessment_destroy:
 * @ptr: pointer to a #idmef_assessment_t object.
 *
 * Destroy @ptr and all of it's children.
 * The objects are only destroyed if their reference count reach zero.
 */

void idmef_assessment_destroy(idmef_assessment_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( --ptr->refcount )
                return;

        idmef_assessment_destroy_internal(ptr);
        free(ptr);
}

/**
 * idmef_assessment_get_impact:
 * @ptr: pointer to a #idmef_assessment_t object.
 *
 * Get impact children of the #idmef_assessment_t object.
 *
 * Returns: a pointer to a idmef_impact_t object, or NULL if the children object is not set.
 */
idmef_impact_t *idmef_assessment_get_impact(idmef_assessment_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->impact;
}

/**
 * idmef_assessment_set_impact:
 * @ptr: pointer to a #idmef_assessment_t object.
 * @impact: pointer to a #idmef_impact_t object.
 *
 * Set @impact object as a children of @ptr.
 * if @ptr already contain an @impact object, then it is destroyed,
 * and updated to point to the provided @impact object.
 */

void idmef_assessment_set_impact(idmef_assessment_t *ptr, idmef_impact_t *impact)
{
        prelude_return_if_fail(ptr);

        if ( ptr->impact )
                idmef_impact_destroy(ptr->impact);

        ptr->impact = impact;
}

/**
 * idmef_assessment_new_impact:
 * @ptr: pointer to a #idmef_assessment_t object.
 * @ret: pointer to an address where to store the created #idmef_impact_t object.
 *
 * Create a new impact object, children of #idmef_assessment_t.
 * If @ptr already contain a #idmef_impact_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_assessment_new_impact(idmef_assessment_t *ptr, idmef_impact_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->impact ) {
                retval = idmef_impact_new(&ptr->impact);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->impact;
        return 0;
}

/**
 * idmef_assessment_get_next_action:
 * @assessment: pointer to a #idmef_assessment_t object.
 * @action_cur: pointer to a #idmef_action_t object.
 *
 * Get the next #idmef_action_t object listed in @ptr.
 * When iterating over the idmef_action_t object listed in @ptr,
 * @object should be set to the latest returned #idmef_action_t object.
 *
 * Returns: the next #idmef_action_t in the list.
 */
idmef_action_t *idmef_assessment_get_next_action(idmef_assessment_t *assessment, idmef_action_t *action_cur)
{
        prelude_list_t *tmp = (action_cur) ? &((prelude_linked_object_t *) action_cur)->_list : NULL;

        prelude_return_val_if_fail(assessment, NULL);

        prelude_list_for_each_continue(&assessment->action_list, tmp)
                return prelude_linked_object_get_object(tmp);

        return NULL;
}


/**
 * idmef_assessment_set_action:
 * @ptr: pointer to a #idmef_assessment_t object.
 * @object: pointer to a #idmef_action_t object.
 * @pos: Position in the list.
 *
 * Add @object to position @pos of @ptr list of #idmef_action_t object.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 */
void idmef_assessment_set_action(idmef_assessment_t *ptr, idmef_action_t *object, int pos)
{
        prelude_return_if_fail(ptr);
        prelude_return_if_fail(object);

        if ( ! prelude_list_is_empty(&((prelude_linked_object_t *) object)->_list) )
                prelude_list_del_init(&((prelude_linked_object_t *) object)->_list);

        list_insert(&ptr->action_list, &((prelude_linked_object_t *) object)->_list, pos);
}


/**
 * idmef_assessment_new_action:
 * @ptr: pointer to a #idmef_assessment_t object.
 * @ret: pointer to an address where to store the created #idmef_action_t object.
 * @pos: position in the list.
 *
 * Create a new #idmef_action_t children of @ptr, and add it to position @pos of
 * @ptr list of #idmef_action_t object. The created #idmef_action_t object is
 * stored in @ret.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_assessment_new_action(idmef_assessment_t *ptr, idmef_action_t **ret, int pos)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        retval = idmef_action_new(ret);
        if ( retval < 0 )
                return retval;

        list_insert(&ptr->action_list, &((prelude_linked_object_t *)(*ret))->_list, pos);

        return 0;
}


/**
 * idmef_assessment_get_confidence:
 * @ptr: pointer to a #idmef_assessment_t object.
 *
 * Get confidence children of the #idmef_assessment_t object.
 *
 * Returns: a pointer to a idmef_confidence_t object, or NULL if the children object is not set.
 */
idmef_confidence_t *idmef_assessment_get_confidence(idmef_assessment_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->confidence;
}

/**
 * idmef_assessment_set_confidence:
 * @ptr: pointer to a #idmef_assessment_t object.
 * @confidence: pointer to a #idmef_confidence_t object.
 *
 * Set @confidence object as a children of @ptr.
 * if @ptr already contain an @confidence object, then it is destroyed,
 * and updated to point to the provided @confidence object.
 */

void idmef_assessment_set_confidence(idmef_assessment_t *ptr, idmef_confidence_t *confidence)
{
        prelude_return_if_fail(ptr);

        if ( ptr->confidence )
                idmef_confidence_destroy(ptr->confidence);

        ptr->confidence = confidence;
}

/**
 * idmef_assessment_new_confidence:
 * @ptr: pointer to a #idmef_assessment_t object.
 * @ret: pointer to an address where to store the created #idmef_confidence_t object.
 *
 * Create a new confidence object, children of #idmef_assessment_t.
 * If @ptr already contain a #idmef_confidence_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_assessment_new_confidence(idmef_assessment_t *ptr, idmef_confidence_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->confidence ) {
                retval = idmef_confidence_new(&ptr->confidence);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->confidence;
        return 0;
}

/**
 * idmef_assessment_copy:
 * @src: Source of the copy.
 * @dst: Where to copy the object.
 *
 * Copy a new #idmef_assessment_t object from @src to @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_assessment_copy(const idmef_assessment_t *src, idmef_assessment_t *dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));
        prelude_return_val_if_fail(dst, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = 0;

        if ( dst->impact ) {
                idmef_impact_destroy(dst->impact);
                dst->impact = NULL;
        }

        if ( src->impact ) {
                ret = idmef_impact_clone(src->impact, &dst->impact);
                if ( ret < 0 )
                        return ret;
        }

        {
                prelude_list_t *n, *tmp;
                idmef_action_t *entry, *new;

                prelude_list_for_each_safe(&dst->action_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        idmef_action_destroy(entry);
                }

                prelude_list_for_each_safe(&src->action_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        idmef_action_clone(entry, &new);
                        prelude_list_add_tail(&dst->action_list, &((prelude_linked_object_t *) new)->_list);
                }
        }

        if ( dst->confidence ) {
                idmef_confidence_destroy(dst->confidence);
                dst->confidence = NULL;
        }

        if ( src->confidence ) {
                ret = idmef_confidence_clone(src->confidence, &dst->confidence);
                if ( ret < 0 )
                        return ret;
        }

        return 0;
}

/**
 * idmef_assessment_clone:
 * @src: Object to be cloned.
 * @dst: Address where to store the pointer to the cloned object.
 *
 * Create a copy of @src, and store it in @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_assessment_clone(idmef_assessment_t *src, idmef_assessment_t **dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = idmef_assessment_new(dst);
        if ( ret < 0 )
                return ret;

        return idmef_assessment_copy(src, *dst);
}

/**
 * idmef_assessment_compare:
 * @obj1: Object to compare with @obj2.
 * @obj2: Object to compare with @obj1.
 *
 * Compare @obj1 with @obj2.
 *
 * Returns: 0 on match, a negative value on comparison failure.
 */
int idmef_assessment_compare(const idmef_assessment_t *obj1, const idmef_assessment_t *obj2)
{
        int ret = 0;

        if ( obj1 == NULL && obj2 == NULL )
                return 0;

        else if ( obj1 == NULL || obj2 == NULL )
                return -1;

        ret = idmef_impact_compare(obj1->impact, obj2->impact);
        if ( ret != 0 )
                return ret;

        {
                prelude_list_t *tmp1, *tmp2;
                idmef_action_t *entry1, *entry2;

                tmp1 = tmp2 = NULL;
                do {
                        entry1 = entry2 = NULL;

                        prelude_list_for_each_continue(&obj1->action_list, tmp1) {
                                entry1 = prelude_linked_object_get_object(tmp1);
                                break;
                        }

                        prelude_list_for_each_continue(&obj2->action_list, tmp2) {
                                entry2 = prelude_linked_object_get_object(tmp2);
                                break;
                        }

                        ret = idmef_action_compare(entry1, entry2);
                        if ( ret != 0 )
                                return ret;

                } while ( entry1 && entry2 );
        }

        ret = idmef_confidence_compare(obj1->confidence, obj2->confidence);
        if ( ret != 0 )
                return ret;

        return ret;
}

/**
 * idmef_tool_alert_new:
 * @ret: Pointer where to store the created #idmef_tool_alert_t object.
 *
 * Create a new #idmef_tool_alert_t object.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_tool_alert_new(idmef_tool_alert_t **ret)
{
        *ret = calloc(1, sizeof(**ret));
        if ( ! *ret )
                return prelude_error_from_errno(errno);

        (*ret)->_idmef_object_id = IDMEF_CLASS_ID_TOOL_ALERT;

        (*ret)->refcount = 1;

        prelude_list_init(&(*ret)->alertident_list);


        {
                int retval = prelude_string_new(&(*ret)->name);

                if ( retval < 0 ) {
                        idmef_tool_alert_destroy(*ret);
                        *ret = NULL;
                        return retval;
                }
        }

        return 0;

}

/**
 * idmef_tool_alert_ref:
 * @tool_alert: pointer to a #idmef_tool_alert_t object.
 *
 * Increase @tool_alert reference count, so that it can be referenced
 * multiple time.
 *
 * Returns: a pointer to @tool_alert.
 */
idmef_tool_alert_t *idmef_tool_alert_ref(idmef_tool_alert_t *tool_alert)
{
        prelude_return_val_if_fail(tool_alert, NULL);
        tool_alert->refcount++;

        return tool_alert;
}

int _idmef_tool_alert_get_child(void *p, idmef_class_child_id_t child, void **childptr)
{
        idmef_tool_alert_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));
        *childptr = NULL;

        switch ( child ) {

                case 0:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->name, TRUE);
                case 1:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->command, TRUE);
                case 2:
                        *childptr = &ptr->alertident_list;
                        return 0;

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_tool_alert_new_child(void *p, idmef_class_child_id_t child, int n, void **ret)
{
        idmef_tool_alert_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        return idmef_tool_alert_new_name(ptr, (prelude_string_t **) ret);

                case 1:
                        return idmef_tool_alert_new_command(ptr, (prelude_string_t **) ret);

                case 2: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n == IDMEF_LIST_APPEND || n == IDMEF_LIST_PREPEND )
                               return idmef_tool_alert_new_alertident(ptr, (idmef_alertident_t **) ret, n);

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->alertident_list, tmp) {
                                       if ( i++ == n ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->alertident_list, tmp) {
                                       if ( i++ == pos ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }

                        return idmef_tool_alert_new_alertident(ptr, (idmef_alertident_t **) ret, n);
                }

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_tool_alert_destroy_child(void *p, idmef_class_child_id_t child, int n)
{
        idmef_tool_alert_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        if ( ptr->name ) {
                                prelude_string_destroy(ptr->name);
                                ptr->name = NULL;
                        }

                        return 0;

                case 1:
                        if ( ptr->command ) {
                                prelude_string_destroy(ptr->command);
                                ptr->command = NULL;
                        }

                        return 0;

                case 2: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->alertident_list, tmp) {
                                       if ( i++ == n ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               idmef_alertident_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->alertident_list, tmp) {
                                       if ( i++ == pos ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               idmef_alertident_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }
                }

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

static void idmef_tool_alert_destroy_internal(idmef_tool_alert_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( ptr->name ) {
                prelude_string_destroy(ptr->name);
                ptr->name = NULL;
        }

        if ( ptr->command ) {
                prelude_string_destroy(ptr->command);
                ptr->command = NULL;
        }

        {
                prelude_list_t *n, *tmp;
                idmef_alertident_t *entry;

                prelude_list_for_each_safe(&ptr->alertident_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        prelude_list_del_init(tmp);
                        idmef_alertident_destroy(entry);
                }
        }


        /* free() should be done by the caller */
}

/**
 * idmef_tool_alert_destroy:
 * @ptr: pointer to a #idmef_tool_alert_t object.
 *
 * Destroy @ptr and all of it's children.
 * The objects are only destroyed if their reference count reach zero.
 */

void idmef_tool_alert_destroy(idmef_tool_alert_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( --ptr->refcount )
                return;

        idmef_tool_alert_destroy_internal(ptr);
        free(ptr);
}

/**
 * idmef_tool_alert_get_name:
 * @ptr: pointer to a #idmef_tool_alert_t object.
 *
 * Get name children of the #idmef_tool_alert_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_tool_alert_get_name(idmef_tool_alert_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->name;
}

/**
 * idmef_tool_alert_set_name:
 * @ptr: pointer to a #idmef_tool_alert_t object.
 * @name: pointer to a #prelude_string_t object.
 *
 * Set @name object as a children of @ptr.
 * if @ptr already contain an @name object, then it is destroyed,
 * and updated to point to the provided @name object.
 */

void idmef_tool_alert_set_name(idmef_tool_alert_t *ptr, prelude_string_t *name)
{
        prelude_return_if_fail(ptr);

        if ( ptr->name )
                prelude_string_destroy(ptr->name);

        ptr->name = name;
}

/**
 * idmef_tool_alert_new_name:
 * @ptr: pointer to a #idmef_tool_alert_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new name object, children of #idmef_tool_alert_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_tool_alert_new_name(idmef_tool_alert_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->name ) {
                retval = prelude_string_new(&ptr->name);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->name;
        return 0;
}

/**
 * idmef_tool_alert_get_command:
 * @ptr: pointer to a #idmef_tool_alert_t object.
 *
 * Get command children of the #idmef_tool_alert_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_tool_alert_get_command(idmef_tool_alert_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->command;
}

/**
 * idmef_tool_alert_set_command:
 * @ptr: pointer to a #idmef_tool_alert_t object.
 * @command: pointer to a #prelude_string_t object.
 *
 * Set @command object as a children of @ptr.
 * if @ptr already contain an @command object, then it is destroyed,
 * and updated to point to the provided @command object.
 */

void idmef_tool_alert_set_command(idmef_tool_alert_t *ptr, prelude_string_t *command)
{
        prelude_return_if_fail(ptr);

        if ( ptr->command )
                prelude_string_destroy(ptr->command);

        ptr->command = command;
}

/**
 * idmef_tool_alert_new_command:
 * @ptr: pointer to a #idmef_tool_alert_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new command object, children of #idmef_tool_alert_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_tool_alert_new_command(idmef_tool_alert_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->command ) {
                retval = prelude_string_new(&ptr->command);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->command;
        return 0;
}

/**
 * idmef_tool_alert_get_next_alertident:
 * @tool_alert: pointer to a #idmef_tool_alert_t object.
 * @alertident_cur: pointer to a #idmef_alertident_t object.
 *
 * Get the next #idmef_alertident_t object listed in @ptr.
 * When iterating over the idmef_alertident_t object listed in @ptr,
 * @object should be set to the latest returned #idmef_alertident_t object.
 *
 * Returns: the next #idmef_alertident_t in the list.
 */
idmef_alertident_t *idmef_tool_alert_get_next_alertident(idmef_tool_alert_t *tool_alert, idmef_alertident_t *alertident_cur)
{
        prelude_list_t *tmp = (alertident_cur) ? &((prelude_linked_object_t *) alertident_cur)->_list : NULL;

        prelude_return_val_if_fail(tool_alert, NULL);

        prelude_list_for_each_continue(&tool_alert->alertident_list, tmp)
                return prelude_linked_object_get_object(tmp);

        return NULL;
}


/**
 * idmef_tool_alert_set_alertident:
 * @ptr: pointer to a #idmef_tool_alert_t object.
 * @object: pointer to a #idmef_alertident_t object.
 * @pos: Position in the list.
 *
 * Add @object to position @pos of @ptr list of #idmef_alertident_t object.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 */
void idmef_tool_alert_set_alertident(idmef_tool_alert_t *ptr, idmef_alertident_t *object, int pos)
{
        prelude_return_if_fail(ptr);
        prelude_return_if_fail(object);

        if ( ! prelude_list_is_empty(&((prelude_linked_object_t *) object)->_list) )
                prelude_list_del_init(&((prelude_linked_object_t *) object)->_list);

        list_insert(&ptr->alertident_list, &((prelude_linked_object_t *) object)->_list, pos);
}


/**
 * idmef_tool_alert_new_alertident:
 * @ptr: pointer to a #idmef_tool_alert_t object.
 * @ret: pointer to an address where to store the created #idmef_alertident_t object.
 * @pos: position in the list.
 *
 * Create a new #idmef_alertident_t children of @ptr, and add it to position @pos of
 * @ptr list of #idmef_alertident_t object. The created #idmef_alertident_t object is
 * stored in @ret.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_tool_alert_new_alertident(idmef_tool_alert_t *ptr, idmef_alertident_t **ret, int pos)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        retval = idmef_alertident_new(ret);
        if ( retval < 0 )
                return retval;

        list_insert(&ptr->alertident_list, &((prelude_linked_object_t *)(*ret))->_list, pos);

        return 0;
}


/**
 * idmef_tool_alert_copy:
 * @src: Source of the copy.
 * @dst: Where to copy the object.
 *
 * Copy a new #idmef_tool_alert_t object from @src to @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_tool_alert_copy(const idmef_tool_alert_t *src, idmef_tool_alert_t *dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));
        prelude_return_val_if_fail(dst, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = 0;

        if ( src->name ) {
                ret = prelude_string_copy(src->name, dst->name);
                if ( ret < 0 )
                        return ret;
        }

        if ( dst->command ) {
                prelude_string_destroy(dst->command);
                dst->command = NULL;
        }

        if ( src->command ) {
                ret = prelude_string_clone(src->command, &dst->command);
                if ( ret < 0 )
                        return ret;
        }

        {
                prelude_list_t *n, *tmp;
                idmef_alertident_t *entry, *new;

                prelude_list_for_each_safe(&dst->alertident_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        idmef_alertident_destroy(entry);
                }

                prelude_list_for_each_safe(&src->alertident_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        idmef_alertident_clone(entry, &new);
                        prelude_list_add_tail(&dst->alertident_list, &((prelude_linked_object_t *) new)->_list);
                }
        }

        return 0;
}

/**
 * idmef_tool_alert_clone:
 * @src: Object to be cloned.
 * @dst: Address where to store the pointer to the cloned object.
 *
 * Create a copy of @src, and store it in @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_tool_alert_clone(idmef_tool_alert_t *src, idmef_tool_alert_t **dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = idmef_tool_alert_new(dst);
        if ( ret < 0 )
                return ret;

        return idmef_tool_alert_copy(src, *dst);
}

/**
 * idmef_tool_alert_compare:
 * @obj1: Object to compare with @obj2.
 * @obj2: Object to compare with @obj1.
 *
 * Compare @obj1 with @obj2.
 *
 * Returns: 0 on match, a negative value on comparison failure.
 */
int idmef_tool_alert_compare(const idmef_tool_alert_t *obj1, const idmef_tool_alert_t *obj2)
{
        int ret = 0;

        if ( obj1 == NULL && obj2 == NULL )
                return 0;

        else if ( obj1 == NULL || obj2 == NULL )
                return -1;

        ret = prelude_string_compare(obj1->name, obj2->name);
        if ( ret != 0 )
                return ret;

        ret = prelude_string_compare(obj1->command, obj2->command);
        if ( ret != 0 )
                return ret;

        {
                prelude_list_t *tmp1, *tmp2;
                idmef_alertident_t *entry1, *entry2;

                tmp1 = tmp2 = NULL;
                do {
                        entry1 = entry2 = NULL;

                        prelude_list_for_each_continue(&obj1->alertident_list, tmp1) {
                                entry1 = prelude_linked_object_get_object(tmp1);
                                break;
                        }

                        prelude_list_for_each_continue(&obj2->alertident_list, tmp2) {
                                entry2 = prelude_linked_object_get_object(tmp2);
                                break;
                        }

                        ret = idmef_alertident_compare(entry1, entry2);
                        if ( ret != 0 )
                                return ret;

                } while ( entry1 && entry2 );
        }

        return ret;
}

/**
 * idmef_correlation_alert_new:
 * @ret: Pointer where to store the created #idmef_correlation_alert_t object.
 *
 * Create a new #idmef_correlation_alert_t object.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_correlation_alert_new(idmef_correlation_alert_t **ret)
{
        *ret = calloc(1, sizeof(**ret));
        if ( ! *ret )
                return prelude_error_from_errno(errno);

        (*ret)->_idmef_object_id = IDMEF_CLASS_ID_CORRELATION_ALERT;

        (*ret)->refcount = 1;

        prelude_list_init(&(*ret)->alertident_list);


        {
                int retval = prelude_string_new(&(*ret)->name);

                if ( retval < 0 ) {
                        idmef_correlation_alert_destroy(*ret);
                        *ret = NULL;
                        return retval;
                }
        }

        return 0;

}

/**
 * idmef_correlation_alert_ref:
 * @correlation_alert: pointer to a #idmef_correlation_alert_t object.
 *
 * Increase @correlation_alert reference count, so that it can be referenced
 * multiple time.
 *
 * Returns: a pointer to @correlation_alert.
 */
idmef_correlation_alert_t *idmef_correlation_alert_ref(idmef_correlation_alert_t *correlation_alert)
{
        prelude_return_val_if_fail(correlation_alert, NULL);
        correlation_alert->refcount++;

        return correlation_alert;
}

int _idmef_correlation_alert_get_child(void *p, idmef_class_child_id_t child, void **childptr)
{
        idmef_correlation_alert_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));
        *childptr = NULL;

        switch ( child ) {

                case 0:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->name, TRUE);
                case 1:
                        *childptr = &ptr->alertident_list;
                        return 0;

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_correlation_alert_new_child(void *p, idmef_class_child_id_t child, int n, void **ret)
{
        idmef_correlation_alert_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        return idmef_correlation_alert_new_name(ptr, (prelude_string_t **) ret);

                case 1: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n == IDMEF_LIST_APPEND || n == IDMEF_LIST_PREPEND )
                               return idmef_correlation_alert_new_alertident(ptr, (idmef_alertident_t **) ret, n);

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->alertident_list, tmp) {
                                       if ( i++ == n ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->alertident_list, tmp) {
                                       if ( i++ == pos ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }

                        return idmef_correlation_alert_new_alertident(ptr, (idmef_alertident_t **) ret, n);
                }

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_correlation_alert_destroy_child(void *p, idmef_class_child_id_t child, int n)
{
        idmef_correlation_alert_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        if ( ptr->name ) {
                                prelude_string_destroy(ptr->name);
                                ptr->name = NULL;
                        }

                        return 0;

                case 1: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->alertident_list, tmp) {
                                       if ( i++ == n ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               idmef_alertident_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->alertident_list, tmp) {
                                       if ( i++ == pos ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               idmef_alertident_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }
                }

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

static void idmef_correlation_alert_destroy_internal(idmef_correlation_alert_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( ptr->name ) {
                prelude_string_destroy(ptr->name);
                ptr->name = NULL;
        }

        {
                prelude_list_t *n, *tmp;
                idmef_alertident_t *entry;

                prelude_list_for_each_safe(&ptr->alertident_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        prelude_list_del_init(tmp);
                        idmef_alertident_destroy(entry);
                }
        }


        /* free() should be done by the caller */
}

/**
 * idmef_correlation_alert_destroy:
 * @ptr: pointer to a #idmef_correlation_alert_t object.
 *
 * Destroy @ptr and all of it's children.
 * The objects are only destroyed if their reference count reach zero.
 */

void idmef_correlation_alert_destroy(idmef_correlation_alert_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( --ptr->refcount )
                return;

        idmef_correlation_alert_destroy_internal(ptr);
        free(ptr);
}

/**
 * idmef_correlation_alert_get_name:
 * @ptr: pointer to a #idmef_correlation_alert_t object.
 *
 * Get name children of the #idmef_correlation_alert_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_correlation_alert_get_name(idmef_correlation_alert_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->name;
}

/**
 * idmef_correlation_alert_set_name:
 * @ptr: pointer to a #idmef_correlation_alert_t object.
 * @name: pointer to a #prelude_string_t object.
 *
 * Set @name object as a children of @ptr.
 * if @ptr already contain an @name object, then it is destroyed,
 * and updated to point to the provided @name object.
 */

void idmef_correlation_alert_set_name(idmef_correlation_alert_t *ptr, prelude_string_t *name)
{
        prelude_return_if_fail(ptr);

        if ( ptr->name )
                prelude_string_destroy(ptr->name);

        ptr->name = name;
}

/**
 * idmef_correlation_alert_new_name:
 * @ptr: pointer to a #idmef_correlation_alert_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new name object, children of #idmef_correlation_alert_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_correlation_alert_new_name(idmef_correlation_alert_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->name ) {
                retval = prelude_string_new(&ptr->name);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->name;
        return 0;
}

/**
 * idmef_correlation_alert_get_next_alertident:
 * @correlation_alert: pointer to a #idmef_correlation_alert_t object.
 * @alertident_cur: pointer to a #idmef_alertident_t object.
 *
 * Get the next #idmef_alertident_t object listed in @ptr.
 * When iterating over the idmef_alertident_t object listed in @ptr,
 * @object should be set to the latest returned #idmef_alertident_t object.
 *
 * Returns: the next #idmef_alertident_t in the list.
 */
idmef_alertident_t *idmef_correlation_alert_get_next_alertident(idmef_correlation_alert_t *correlation_alert, idmef_alertident_t *alertident_cur)
{
        prelude_list_t *tmp = (alertident_cur) ? &((prelude_linked_object_t *) alertident_cur)->_list : NULL;

        prelude_return_val_if_fail(correlation_alert, NULL);

        prelude_list_for_each_continue(&correlation_alert->alertident_list, tmp)
                return prelude_linked_object_get_object(tmp);

        return NULL;
}


/**
 * idmef_correlation_alert_set_alertident:
 * @ptr: pointer to a #idmef_correlation_alert_t object.
 * @object: pointer to a #idmef_alertident_t object.
 * @pos: Position in the list.
 *
 * Add @object to position @pos of @ptr list of #idmef_alertident_t object.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 */
void idmef_correlation_alert_set_alertident(idmef_correlation_alert_t *ptr, idmef_alertident_t *object, int pos)
{
        prelude_return_if_fail(ptr);
        prelude_return_if_fail(object);

        if ( ! prelude_list_is_empty(&((prelude_linked_object_t *) object)->_list) )
                prelude_list_del_init(&((prelude_linked_object_t *) object)->_list);

        list_insert(&ptr->alertident_list, &((prelude_linked_object_t *) object)->_list, pos);
}


/**
 * idmef_correlation_alert_new_alertident:
 * @ptr: pointer to a #idmef_correlation_alert_t object.
 * @ret: pointer to an address where to store the created #idmef_alertident_t object.
 * @pos: position in the list.
 *
 * Create a new #idmef_alertident_t children of @ptr, and add it to position @pos of
 * @ptr list of #idmef_alertident_t object. The created #idmef_alertident_t object is
 * stored in @ret.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_correlation_alert_new_alertident(idmef_correlation_alert_t *ptr, idmef_alertident_t **ret, int pos)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        retval = idmef_alertident_new(ret);
        if ( retval < 0 )
                return retval;

        list_insert(&ptr->alertident_list, &((prelude_linked_object_t *)(*ret))->_list, pos);

        return 0;
}


/**
 * idmef_correlation_alert_copy:
 * @src: Source of the copy.
 * @dst: Where to copy the object.
 *
 * Copy a new #idmef_correlation_alert_t object from @src to @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_correlation_alert_copy(const idmef_correlation_alert_t *src, idmef_correlation_alert_t *dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));
        prelude_return_val_if_fail(dst, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = 0;

        if ( src->name ) {
                ret = prelude_string_copy(src->name, dst->name);
                if ( ret < 0 )
                        return ret;
        }

        {
                prelude_list_t *n, *tmp;
                idmef_alertident_t *entry, *new;

                prelude_list_for_each_safe(&dst->alertident_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        idmef_alertident_destroy(entry);
                }

                prelude_list_for_each_safe(&src->alertident_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        idmef_alertident_clone(entry, &new);
                        prelude_list_add_tail(&dst->alertident_list, &((prelude_linked_object_t *) new)->_list);
                }
        }

        return 0;
}

/**
 * idmef_correlation_alert_clone:
 * @src: Object to be cloned.
 * @dst: Address where to store the pointer to the cloned object.
 *
 * Create a copy of @src, and store it in @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_correlation_alert_clone(idmef_correlation_alert_t *src, idmef_correlation_alert_t **dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = idmef_correlation_alert_new(dst);
        if ( ret < 0 )
                return ret;

        return idmef_correlation_alert_copy(src, *dst);
}

/**
 * idmef_correlation_alert_compare:
 * @obj1: Object to compare with @obj2.
 * @obj2: Object to compare with @obj1.
 *
 * Compare @obj1 with @obj2.
 *
 * Returns: 0 on match, a negative value on comparison failure.
 */
int idmef_correlation_alert_compare(const idmef_correlation_alert_t *obj1, const idmef_correlation_alert_t *obj2)
{
        int ret = 0;

        if ( obj1 == NULL && obj2 == NULL )
                return 0;

        else if ( obj1 == NULL || obj2 == NULL )
                return -1;

        ret = prelude_string_compare(obj1->name, obj2->name);
        if ( ret != 0 )
                return ret;

        {
                prelude_list_t *tmp1, *tmp2;
                idmef_alertident_t *entry1, *entry2;

                tmp1 = tmp2 = NULL;
                do {
                        entry1 = entry2 = NULL;

                        prelude_list_for_each_continue(&obj1->alertident_list, tmp1) {
                                entry1 = prelude_linked_object_get_object(tmp1);
                                break;
                        }

                        prelude_list_for_each_continue(&obj2->alertident_list, tmp2) {
                                entry2 = prelude_linked_object_get_object(tmp2);
                                break;
                        }

                        ret = idmef_alertident_compare(entry1, entry2);
                        if ( ret != 0 )
                                return ret;

                } while ( entry1 && entry2 );
        }

        return ret;
}

/**
 * idmef_overflow_alert_new:
 * @ret: Pointer where to store the created #idmef_overflow_alert_t object.
 *
 * Create a new #idmef_overflow_alert_t object.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_overflow_alert_new(idmef_overflow_alert_t **ret)
{
        *ret = calloc(1, sizeof(**ret));
        if ( ! *ret )
                return prelude_error_from_errno(errno);

        (*ret)->_idmef_object_id = IDMEF_CLASS_ID_OVERFLOW_ALERT;

        (*ret)->refcount = 1;

        {
                int retval = prelude_string_new(&(*ret)->program);

                if ( retval < 0 ) {
                        idmef_overflow_alert_destroy(*ret);
                        *ret = NULL;
                        return retval;
                }
        }

        return 0;

}

/**
 * idmef_overflow_alert_ref:
 * @overflow_alert: pointer to a #idmef_overflow_alert_t object.
 *
 * Increase @overflow_alert reference count, so that it can be referenced
 * multiple time.
 *
 * Returns: a pointer to @overflow_alert.
 */
idmef_overflow_alert_t *idmef_overflow_alert_ref(idmef_overflow_alert_t *overflow_alert)
{
        prelude_return_val_if_fail(overflow_alert, NULL);
        overflow_alert->refcount++;

        return overflow_alert;
}

int _idmef_overflow_alert_get_child(void *p, idmef_class_child_id_t child, void **childptr)
{
        idmef_overflow_alert_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));
        *childptr = NULL;

        switch ( child ) {

                case 0:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->program, TRUE);
                case 1:
                       return (ptr->size_is_set) ? idmef_value_new_uint32((idmef_value_t **) childptr, ptr->size) : 0;

                case 2:
                       return get_value_from_data((idmef_value_t **) childptr,  ptr->buffer, TRUE);
                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_overflow_alert_new_child(void *p, idmef_class_child_id_t child, int n, void **ret)
{
        idmef_overflow_alert_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        return idmef_overflow_alert_new_program(ptr, (prelude_string_t **) ret);

                case 1:
                        return idmef_overflow_alert_new_size(ptr, (uint32_t **) ret);

                case 2:
                        return idmef_overflow_alert_new_buffer(ptr, (idmef_data_t **) ret);

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_overflow_alert_destroy_child(void *p, idmef_class_child_id_t child, int n)
{
        idmef_overflow_alert_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        if ( ptr->program ) {
                                prelude_string_destroy(ptr->program);
                                ptr->program = NULL;
                        }

                        return 0;

                case 1:
                        ptr->size_is_set = 0;
                        return 0;

                case 2:
                        if ( ptr->buffer ) {
                                idmef_data_destroy(ptr->buffer);
                                ptr->buffer = NULL;
                        }

                        return 0;

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

static void idmef_overflow_alert_destroy_internal(idmef_overflow_alert_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( ptr->program ) {
                prelude_string_destroy(ptr->program);
                ptr->program = NULL;
        }

        if ( ptr->buffer ) {
                idmef_data_destroy(ptr->buffer);
                ptr->buffer = NULL;
        }


        /* free() should be done by the caller */
}

/**
 * idmef_overflow_alert_destroy:
 * @ptr: pointer to a #idmef_overflow_alert_t object.
 *
 * Destroy @ptr and all of it's children.
 * The objects are only destroyed if their reference count reach zero.
 */

void idmef_overflow_alert_destroy(idmef_overflow_alert_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( --ptr->refcount )
                return;

        idmef_overflow_alert_destroy_internal(ptr);
        free(ptr);
}

/**
 * idmef_overflow_alert_get_program:
 * @ptr: pointer to a #idmef_overflow_alert_t object.
 *
 * Get program children of the #idmef_overflow_alert_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_overflow_alert_get_program(idmef_overflow_alert_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->program;
}

/**
 * idmef_overflow_alert_set_program:
 * @ptr: pointer to a #idmef_overflow_alert_t object.
 * @program: pointer to a #prelude_string_t object.
 *
 * Set @program object as a children of @ptr.
 * if @ptr already contain an @program object, then it is destroyed,
 * and updated to point to the provided @program object.
 */

void idmef_overflow_alert_set_program(idmef_overflow_alert_t *ptr, prelude_string_t *program)
{
        prelude_return_if_fail(ptr);

        if ( ptr->program )
                prelude_string_destroy(ptr->program);

        ptr->program = program;
}

/**
 * idmef_overflow_alert_new_program:
 * @ptr: pointer to a #idmef_overflow_alert_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new program object, children of #idmef_overflow_alert_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_overflow_alert_new_program(idmef_overflow_alert_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->program ) {
                retval = prelude_string_new(&ptr->program);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->program;
        return 0;
}

/**
 * idmef_overflow_alert_get_size:
 * @ptr: pointer to a #idmef_overflow_alert_t object.
 *
 * Get size children of the #idmef_overflow_alert_t object.
 *
 * Returns: a pointer to a uint32_t object, or NULL if the children object is not set.
 */
uint32_t *idmef_overflow_alert_get_size(idmef_overflow_alert_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->size_is_set ? &ptr->size : NULL;
}

/**
 * idmef_overflow_alert_set_size:
 * @ptr: pointer to a #idmef_overflow_alert_t object.
 * @size: pointer to a #uint32_t object.
 *
 * Set @size object as a children of @ptr.
 * if @ptr already contain an @size object, then it is destroyed,
 * and updated to point to the provided @size object.
 */

void idmef_overflow_alert_set_size(idmef_overflow_alert_t *ptr, uint32_t size)
{
        prelude_return_if_fail(ptr);
        ptr->size = size;
        ptr->size_is_set = 1;
}


void idmef_overflow_alert_unset_size(idmef_overflow_alert_t *ptr)
{
        prelude_return_if_fail(ptr);
        ptr->size_is_set = 0;
}


/**
 * idmef_overflow_alert_new_size:
 * @ptr: pointer to a #idmef_overflow_alert_t object.
 * @ret: pointer to an address where to store the created #uint32_t object.
 *
 * Create a new size object, children of #idmef_overflow_alert_t.
 * If @ptr already contain a #uint32_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_overflow_alert_new_size(idmef_overflow_alert_t *ptr, uint32_t **ret)
{
        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));
        ptr->size_is_set = 1;

        *ret = &ptr->size;
        return 0;
}

/**
 * idmef_overflow_alert_get_buffer:
 * @ptr: pointer to a #idmef_overflow_alert_t object.
 *
 * Get buffer children of the #idmef_overflow_alert_t object.
 *
 * Returns: a pointer to a idmef_data_t object, or NULL if the children object is not set.
 */
idmef_data_t *idmef_overflow_alert_get_buffer(idmef_overflow_alert_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->buffer;
}

/**
 * idmef_overflow_alert_set_buffer:
 * @ptr: pointer to a #idmef_overflow_alert_t object.
 * @buffer: pointer to a #idmef_data_t object.
 *
 * Set @buffer object as a children of @ptr.
 * if @ptr already contain an @buffer object, then it is destroyed,
 * and updated to point to the provided @buffer object.
 */

void idmef_overflow_alert_set_buffer(idmef_overflow_alert_t *ptr, idmef_data_t *buffer)
{
        prelude_return_if_fail(ptr);

        if ( ptr->buffer )
                idmef_data_destroy(ptr->buffer);

        ptr->buffer = buffer;
}

/**
 * idmef_overflow_alert_new_buffer:
 * @ptr: pointer to a #idmef_overflow_alert_t object.
 * @ret: pointer to an address where to store the created #idmef_data_t object.
 *
 * Create a new buffer object, children of #idmef_overflow_alert_t.
 * If @ptr already contain a #idmef_data_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_overflow_alert_new_buffer(idmef_overflow_alert_t *ptr, idmef_data_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->buffer ) {
                retval = idmef_data_new(&ptr->buffer);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->buffer;
        return 0;
}

/**
 * idmef_overflow_alert_copy:
 * @src: Source of the copy.
 * @dst: Where to copy the object.
 *
 * Copy a new #idmef_overflow_alert_t object from @src to @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_overflow_alert_copy(const idmef_overflow_alert_t *src, idmef_overflow_alert_t *dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));
        prelude_return_val_if_fail(dst, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = 0;

        if ( src->program ) {
                ret = prelude_string_copy(src->program, dst->program);
                if ( ret < 0 )
                        return ret;
        }

        dst->size_is_set = src->size_is_set;

        dst->size = src->size;

        if ( dst->buffer ) {
                idmef_data_destroy(dst->buffer);
                dst->buffer = NULL;
        }

        if ( src->buffer ) {
                ret = idmef_data_clone(src->buffer, &dst->buffer);
                if ( ret < 0 )
                        return ret;
        }

        return 0;
}

/**
 * idmef_overflow_alert_clone:
 * @src: Object to be cloned.
 * @dst: Address where to store the pointer to the cloned object.
 *
 * Create a copy of @src, and store it in @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_overflow_alert_clone(idmef_overflow_alert_t *src, idmef_overflow_alert_t **dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = idmef_overflow_alert_new(dst);
        if ( ret < 0 )
                return ret;

        return idmef_overflow_alert_copy(src, *dst);
}

/**
 * idmef_overflow_alert_compare:
 * @obj1: Object to compare with @obj2.
 * @obj2: Object to compare with @obj1.
 *
 * Compare @obj1 with @obj2.
 *
 * Returns: 0 on match, a negative value on comparison failure.
 */
int idmef_overflow_alert_compare(const idmef_overflow_alert_t *obj1, const idmef_overflow_alert_t *obj2)
{
        int ret = 0;

        if ( obj1 == NULL && obj2 == NULL )
                return 0;

        else if ( obj1 == NULL || obj2 == NULL )
                return -1;

        ret = prelude_string_compare(obj1->program, obj2->program);
        if ( ret != 0 )
                return ret;

        if ( obj1->size_is_set != obj2->size_is_set )
                return -1;

        if ( obj1->size_is_set && obj1->size != obj2->size )
                return -1;

        ret = idmef_data_compare(obj1->buffer, obj2->buffer);
        if ( ret != 0 )
                return ret;

        return ret;
}

/**
 * idmef_alert_new:
 * @ret: Pointer where to store the created #idmef_alert_t object.
 *
 * Create a new #idmef_alert_t object.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_alert_new(idmef_alert_t **ret)
{
        *ret = calloc(1, sizeof(**ret));
        if ( ! *ret )
                return prelude_error_from_errno(errno);

        (*ret)->_idmef_object_id = IDMEF_CLASS_ID_ALERT;

        (*ret)->refcount = 1;

        prelude_list_init(&(*ret)->analyzer_list);


        prelude_list_init(&(*ret)->source_list);


        prelude_list_init(&(*ret)->target_list);


        prelude_list_init(&(*ret)->additional_data_list);


        {
                int retval = idmef_time_new(&(*ret)->create_time);

                if ( retval < 0 ) {
                        idmef_alert_destroy(*ret);
                        *ret = NULL;
                        return retval;
                }
        }

        idmef_time_set_from_gettimeofday((*ret)->create_time);

        {
                int retval = idmef_classification_new(&(*ret)->classification);

                if ( retval < 0 ) {
                        idmef_alert_destroy(*ret);
                        *ret = NULL;
                        return retval;
                }
        }

        return 0;

}

/**
 * idmef_alert_ref:
 * @alert: pointer to a #idmef_alert_t object.
 *
 * Increase @alert reference count, so that it can be referenced
 * multiple time.
 *
 * Returns: a pointer to @alert.
 */
idmef_alert_t *idmef_alert_ref(idmef_alert_t *alert)
{
        prelude_return_val_if_fail(alert, NULL);
        alert->refcount++;

        return alert;
}

int _idmef_alert_get_child(void *p, idmef_class_child_id_t child, void **childptr)
{
        idmef_alert_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));
        *childptr = NULL;

        switch ( child ) {

                case 0:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->messageid, TRUE);
                case 1:
                        *childptr = &ptr->analyzer_list;
                        return 0;

                case 2:
                       return get_value_from_time((idmef_value_t **) childptr,  ptr->create_time, TRUE);
                case 3:
                        *childptr = ptr->classification;
                        return 0;

                case 4:
                       return get_value_from_time((idmef_value_t **) childptr,  ptr->detect_time, TRUE);
                case 5:
                       return get_value_from_time((idmef_value_t **) childptr,  ptr->analyzer_time, TRUE);
                case 6:
                        *childptr = &ptr->source_list;
                        return 0;

                case 7:
                        *childptr = &ptr->target_list;
                        return 0;

                case 8:
                        *childptr = ptr->assessment;
                        return 0;

                case 9:
                        *childptr = &ptr->additional_data_list;
                        return 0;

                case 10:
                        *childptr = ( ptr->type == IDMEF_ALERT_TYPE_TOOL ) ? ptr->detail.tool_alert : NULL;
                        return 0;

                case 11:
                        *childptr = ( ptr->type == IDMEF_ALERT_TYPE_CORRELATION ) ? ptr->detail.correlation_alert : NULL;
                        return 0;

                case 12:
                        *childptr = ( ptr->type == IDMEF_ALERT_TYPE_OVERFLOW ) ? ptr->detail.overflow_alert : NULL;
                        return 0;

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_alert_new_child(void *p, idmef_class_child_id_t child, int n, void **ret)
{
        idmef_alert_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        return idmef_alert_new_messageid(ptr, (prelude_string_t **) ret);

                case 1: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n == IDMEF_LIST_APPEND || n == IDMEF_LIST_PREPEND )
                               return idmef_alert_new_analyzer(ptr, (idmef_analyzer_t **) ret, n);

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->analyzer_list, tmp) {
                                       if ( i++ == n ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->analyzer_list, tmp) {
                                       if ( i++ == pos ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }

                        return idmef_alert_new_analyzer(ptr, (idmef_analyzer_t **) ret, n);
                }

                case 2:
                        return idmef_alert_new_create_time(ptr, (idmef_time_t **) ret);

                case 3:
                        return idmef_alert_new_classification(ptr, (idmef_classification_t **) ret);

                case 4:
                        return idmef_alert_new_detect_time(ptr, (idmef_time_t **) ret);

                case 5:
                        return idmef_alert_new_analyzer_time(ptr, (idmef_time_t **) ret);

                case 6: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n == IDMEF_LIST_APPEND || n == IDMEF_LIST_PREPEND )
                               return idmef_alert_new_source(ptr, (idmef_source_t **) ret, n);

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->source_list, tmp) {
                                       if ( i++ == n ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->source_list, tmp) {
                                       if ( i++ == pos ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }

                        return idmef_alert_new_source(ptr, (idmef_source_t **) ret, n);
                }

                case 7: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n == IDMEF_LIST_APPEND || n == IDMEF_LIST_PREPEND )
                               return idmef_alert_new_target(ptr, (idmef_target_t **) ret, n);

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->target_list, tmp) {
                                       if ( i++ == n ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->target_list, tmp) {
                                       if ( i++ == pos ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }

                        return idmef_alert_new_target(ptr, (idmef_target_t **) ret, n);
                }

                case 8:
                        return idmef_alert_new_assessment(ptr, (idmef_assessment_t **) ret);

                case 9: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n == IDMEF_LIST_APPEND || n == IDMEF_LIST_PREPEND )
                               return idmef_alert_new_additional_data(ptr, (idmef_additional_data_t **) ret, n);

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->additional_data_list, tmp) {
                                       if ( i++ == n ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->additional_data_list, tmp) {
                                       if ( i++ == pos ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }

                        return idmef_alert_new_additional_data(ptr, (idmef_additional_data_t **) ret, n);
                }

                case 10:
                        return idmef_alert_new_tool_alert(ptr, (idmef_tool_alert_t **) ret);

                case 11:
                        return idmef_alert_new_correlation_alert(ptr, (idmef_correlation_alert_t **) ret);

                case 12:
                        return idmef_alert_new_overflow_alert(ptr, (idmef_overflow_alert_t **) ret);

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_alert_destroy_child(void *p, idmef_class_child_id_t child, int n)
{
        idmef_alert_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        if ( ptr->messageid ) {
                                prelude_string_destroy(ptr->messageid);
                                ptr->messageid = NULL;
                        }

                        return 0;

                case 1: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->analyzer_list, tmp) {
                                       if ( i++ == n ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               idmef_analyzer_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->analyzer_list, tmp) {
                                       if ( i++ == pos ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               idmef_analyzer_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }
                }

                case 2:
                        if ( ptr->create_time ) {
                                idmef_time_destroy(ptr->create_time);
                                ptr->create_time = NULL;
                        }

                        return 0;

                case 3:
                        if ( ptr->classification ) {
                                idmef_classification_destroy(ptr->classification);
                                ptr->classification = NULL;
                        }

                        return 0;

                case 4:
                        if ( ptr->detect_time ) {
                                idmef_time_destroy(ptr->detect_time);
                                ptr->detect_time = NULL;
                        }

                        return 0;

                case 5:
                        if ( ptr->analyzer_time ) {
                                idmef_time_destroy(ptr->analyzer_time);
                                ptr->analyzer_time = NULL;
                        }

                        return 0;

                case 6: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->source_list, tmp) {
                                       if ( i++ == n ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               idmef_source_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->source_list, tmp) {
                                       if ( i++ == pos ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               idmef_source_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }
                }

                case 7: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->target_list, tmp) {
                                       if ( i++ == n ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               idmef_target_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->target_list, tmp) {
                                       if ( i++ == pos ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               idmef_target_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }
                }

                case 8:
                        if ( ptr->assessment ) {
                                idmef_assessment_destroy(ptr->assessment);
                                ptr->assessment = NULL;
                        }

                        return 0;

                case 9: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->additional_data_list, tmp) {
                                       if ( i++ == n ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               idmef_additional_data_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->additional_data_list, tmp) {
                                       if ( i++ == pos ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               idmef_additional_data_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }
                }

                case 10:
                        if (  ptr->type != IDMEF_ALERT_TYPE_TOOL )
                                return 0;

                        idmef_tool_alert_destroy(ptr->detail.tool_alert);
                        ptr->detail.tool_alert = NULL;
                        ptr->type = 0;

                        return 0;

                case 11:
                        if (  ptr->type != IDMEF_ALERT_TYPE_CORRELATION )
                                return 0;

                        idmef_correlation_alert_destroy(ptr->detail.correlation_alert);
                        ptr->detail.correlation_alert = NULL;
                        ptr->type = 0;

                        return 0;

                case 12:
                        if (  ptr->type != IDMEF_ALERT_TYPE_OVERFLOW )
                                return 0;

                        idmef_overflow_alert_destroy(ptr->detail.overflow_alert);
                        ptr->detail.overflow_alert = NULL;
                        ptr->type = 0;

                        return 0;

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

static void idmef_alert_destroy_internal(idmef_alert_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( ptr->messageid ) {
                prelude_string_destroy(ptr->messageid);
                ptr->messageid = NULL;
        }

        {
                prelude_list_t *n, *tmp;
                idmef_analyzer_t *entry;

                prelude_list_for_each_safe(&ptr->analyzer_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        prelude_list_del_init(tmp);
                        idmef_analyzer_destroy(entry);
                }
        }

        if ( ptr->create_time ) {
                idmef_time_destroy(ptr->create_time);
                ptr->create_time = NULL;
        }

        if ( ptr->classification ) {
                idmef_classification_destroy(ptr->classification);
                ptr->classification = NULL;
        }

        if ( ptr->detect_time ) {
                idmef_time_destroy(ptr->detect_time);
                ptr->detect_time = NULL;
        }

        if ( ptr->analyzer_time ) {
                idmef_time_destroy(ptr->analyzer_time);
                ptr->analyzer_time = NULL;
        }

        {
                prelude_list_t *n, *tmp;
                idmef_source_t *entry;

                prelude_list_for_each_safe(&ptr->source_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        prelude_list_del_init(tmp);
                        idmef_source_destroy(entry);
                }
        }

        {
                prelude_list_t *n, *tmp;
                idmef_target_t *entry;

                prelude_list_for_each_safe(&ptr->target_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        prelude_list_del_init(tmp);
                        idmef_target_destroy(entry);
                }
        }

        if ( ptr->assessment ) {
                idmef_assessment_destroy(ptr->assessment);
                ptr->assessment = NULL;
        }

        {
                prelude_list_t *n, *tmp;
                idmef_additional_data_t *entry;

                prelude_list_for_each_safe(&ptr->additional_data_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        prelude_list_del_init(tmp);
                        idmef_additional_data_destroy(entry);
                }
        }

        switch ( ptr->type ) {

                case IDMEF_ALERT_TYPE_TOOL:
                        idmef_tool_alert_destroy(ptr->detail.tool_alert);
                        ptr->detail.tool_alert = NULL;
                        break;

                case IDMEF_ALERT_TYPE_CORRELATION:
                        idmef_correlation_alert_destroy(ptr->detail.correlation_alert);
                        ptr->detail.correlation_alert = NULL;
                        break;

                case IDMEF_ALERT_TYPE_OVERFLOW:
                        idmef_overflow_alert_destroy(ptr->detail.overflow_alert);
                        ptr->detail.overflow_alert = NULL;
                        break;

                default:
                        break;
        }


        /* free() should be done by the caller */
}

/**
 * idmef_alert_destroy:
 * @ptr: pointer to a #idmef_alert_t object.
 *
 * Destroy @ptr and all of it's children.
 * The objects are only destroyed if their reference count reach zero.
 */

void idmef_alert_destroy(idmef_alert_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( --ptr->refcount )
                return;

        idmef_alert_destroy_internal(ptr);
        free(ptr);
}

/**
 * idmef_alert_get_messageid:
 * @ptr: pointer to a #idmef_alert_t object.
 *
 * Get messageid children of the #idmef_alert_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_alert_get_messageid(idmef_alert_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->messageid;
}

/**
 * idmef_alert_set_messageid:
 * @ptr: pointer to a #idmef_alert_t object.
 * @messageid: pointer to a #prelude_string_t object.
 *
 * Set @messageid object as a children of @ptr.
 * if @ptr already contain an @messageid object, then it is destroyed,
 * and updated to point to the provided @messageid object.
 */

void idmef_alert_set_messageid(idmef_alert_t *ptr, prelude_string_t *messageid)
{
        prelude_return_if_fail(ptr);

        if ( ptr->messageid )
                prelude_string_destroy(ptr->messageid);

        ptr->messageid = messageid;
}

/**
 * idmef_alert_new_messageid:
 * @ptr: pointer to a #idmef_alert_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new messageid object, children of #idmef_alert_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_alert_new_messageid(idmef_alert_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->messageid ) {
                retval = prelude_string_new(&ptr->messageid);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->messageid;
        return 0;
}

/**
 * idmef_alert_get_next_analyzer:
 * @alert: pointer to a #idmef_alert_t object.
 * @analyzer_cur: pointer to a #idmef_analyzer_t object.
 *
 * Get the next #idmef_analyzer_t object listed in @ptr.
 * When iterating over the idmef_analyzer_t object listed in @ptr,
 * @object should be set to the latest returned #idmef_analyzer_t object.
 *
 * Returns: the next #idmef_analyzer_t in the list.
 */
idmef_analyzer_t *idmef_alert_get_next_analyzer(idmef_alert_t *alert, idmef_analyzer_t *analyzer_cur)
{
        prelude_list_t *tmp = (analyzer_cur) ? &((prelude_linked_object_t *) analyzer_cur)->_list : NULL;

        prelude_return_val_if_fail(alert, NULL);

        prelude_list_for_each_continue(&alert->analyzer_list, tmp)
                return prelude_linked_object_get_object(tmp);

        return NULL;
}


/**
 * idmef_alert_set_analyzer:
 * @ptr: pointer to a #idmef_alert_t object.
 * @object: pointer to a #idmef_analyzer_t object.
 * @pos: Position in the list.
 *
 * Add @object to position @pos of @ptr list of #idmef_analyzer_t object.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 */
void idmef_alert_set_analyzer(idmef_alert_t *ptr, idmef_analyzer_t *object, int pos)
{
        prelude_return_if_fail(ptr);
        prelude_return_if_fail(object);

        if ( ! prelude_list_is_empty(&((prelude_linked_object_t *) object)->_list) )
                prelude_list_del_init(&((prelude_linked_object_t *) object)->_list);

        list_insert(&ptr->analyzer_list, &((prelude_linked_object_t *) object)->_list, pos);
}


/**
 * idmef_alert_new_analyzer:
 * @ptr: pointer to a #idmef_alert_t object.
 * @ret: pointer to an address where to store the created #idmef_analyzer_t object.
 * @pos: position in the list.
 *
 * Create a new #idmef_analyzer_t children of @ptr, and add it to position @pos of
 * @ptr list of #idmef_analyzer_t object. The created #idmef_analyzer_t object is
 * stored in @ret.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_alert_new_analyzer(idmef_alert_t *ptr, idmef_analyzer_t **ret, int pos)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        retval = idmef_analyzer_new(ret);
        if ( retval < 0 )
                return retval;

        list_insert(&ptr->analyzer_list, &((prelude_linked_object_t *)(*ret))->_list, pos);

        return 0;
}


/**
 * idmef_alert_get_create_time:
 * @ptr: pointer to a #idmef_alert_t object.
 *
 * Get create_time children of the #idmef_alert_t object.
 *
 * Returns: a pointer to a idmef_time_t object, or NULL if the children object is not set.
 */
idmef_time_t *idmef_alert_get_create_time(idmef_alert_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->create_time;
}

/**
 * idmef_alert_set_create_time:
 * @ptr: pointer to a #idmef_alert_t object.
 * @create_time: pointer to a #idmef_time_t object.
 *
 * Set @create_time object as a children of @ptr.
 * if @ptr already contain an @create_time object, then it is destroyed,
 * and updated to point to the provided @create_time object.
 */

void idmef_alert_set_create_time(idmef_alert_t *ptr, idmef_time_t *create_time)
{
        prelude_return_if_fail(ptr);

        if ( ptr->create_time )
                idmef_time_destroy(ptr->create_time);

        ptr->create_time = create_time;
}

/**
 * idmef_alert_new_create_time:
 * @ptr: pointer to a #idmef_alert_t object.
 * @ret: pointer to an address where to store the created #idmef_time_t object.
 *
 * Create a new create_time object, children of #idmef_alert_t.
 * If @ptr already contain a #idmef_time_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_alert_new_create_time(idmef_alert_t *ptr, idmef_time_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->create_time ) {
                retval = idmef_time_new(&ptr->create_time);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->create_time;
        return 0;
}

/**
 * idmef_alert_get_classification:
 * @ptr: pointer to a #idmef_alert_t object.
 *
 * Get classification children of the #idmef_alert_t object.
 *
 * Returns: a pointer to a idmef_classification_t object, or NULL if the children object is not set.
 */
idmef_classification_t *idmef_alert_get_classification(idmef_alert_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->classification;
}

/**
 * idmef_alert_set_classification:
 * @ptr: pointer to a #idmef_alert_t object.
 * @classification: pointer to a #idmef_classification_t object.
 *
 * Set @classification object as a children of @ptr.
 * if @ptr already contain an @classification object, then it is destroyed,
 * and updated to point to the provided @classification object.
 */

void idmef_alert_set_classification(idmef_alert_t *ptr, idmef_classification_t *classification)
{
        prelude_return_if_fail(ptr);

        if ( ptr->classification )
                idmef_classification_destroy(ptr->classification);

        ptr->classification = classification;
}

/**
 * idmef_alert_new_classification:
 * @ptr: pointer to a #idmef_alert_t object.
 * @ret: pointer to an address where to store the created #idmef_classification_t object.
 *
 * Create a new classification object, children of #idmef_alert_t.
 * If @ptr already contain a #idmef_classification_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_alert_new_classification(idmef_alert_t *ptr, idmef_classification_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->classification ) {
                retval = idmef_classification_new(&ptr->classification);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->classification;
        return 0;
}

/**
 * idmef_alert_get_detect_time:
 * @ptr: pointer to a #idmef_alert_t object.
 *
 * Get detect_time children of the #idmef_alert_t object.
 *
 * Returns: a pointer to a idmef_time_t object, or NULL if the children object is not set.
 */
idmef_time_t *idmef_alert_get_detect_time(idmef_alert_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->detect_time;
}

/**
 * idmef_alert_set_detect_time:
 * @ptr: pointer to a #idmef_alert_t object.
 * @detect_time: pointer to a #idmef_time_t object.
 *
 * Set @detect_time object as a children of @ptr.
 * if @ptr already contain an @detect_time object, then it is destroyed,
 * and updated to point to the provided @detect_time object.
 */

void idmef_alert_set_detect_time(idmef_alert_t *ptr, idmef_time_t *detect_time)
{
        prelude_return_if_fail(ptr);

        if ( ptr->detect_time )
                idmef_time_destroy(ptr->detect_time);

        ptr->detect_time = detect_time;
}

/**
 * idmef_alert_new_detect_time:
 * @ptr: pointer to a #idmef_alert_t object.
 * @ret: pointer to an address where to store the created #idmef_time_t object.
 *
 * Create a new detect_time object, children of #idmef_alert_t.
 * If @ptr already contain a #idmef_time_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_alert_new_detect_time(idmef_alert_t *ptr, idmef_time_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->detect_time ) {
                retval = idmef_time_new(&ptr->detect_time);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->detect_time;
        return 0;
}

/**
 * idmef_alert_get_analyzer_time:
 * @ptr: pointer to a #idmef_alert_t object.
 *
 * Get analyzer_time children of the #idmef_alert_t object.
 *
 * Returns: a pointer to a idmef_time_t object, or NULL if the children object is not set.
 */
idmef_time_t *idmef_alert_get_analyzer_time(idmef_alert_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->analyzer_time;
}

/**
 * idmef_alert_set_analyzer_time:
 * @ptr: pointer to a #idmef_alert_t object.
 * @analyzer_time: pointer to a #idmef_time_t object.
 *
 * Set @analyzer_time object as a children of @ptr.
 * if @ptr already contain an @analyzer_time object, then it is destroyed,
 * and updated to point to the provided @analyzer_time object.
 */

void idmef_alert_set_analyzer_time(idmef_alert_t *ptr, idmef_time_t *analyzer_time)
{
        prelude_return_if_fail(ptr);

        if ( ptr->analyzer_time )
                idmef_time_destroy(ptr->analyzer_time);

        ptr->analyzer_time = analyzer_time;
}

/**
 * idmef_alert_new_analyzer_time:
 * @ptr: pointer to a #idmef_alert_t object.
 * @ret: pointer to an address where to store the created #idmef_time_t object.
 *
 * Create a new analyzer_time object, children of #idmef_alert_t.
 * If @ptr already contain a #idmef_time_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_alert_new_analyzer_time(idmef_alert_t *ptr, idmef_time_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->analyzer_time ) {
                retval = idmef_time_new(&ptr->analyzer_time);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->analyzer_time;
        return 0;
}

/**
 * idmef_alert_get_next_source:
 * @alert: pointer to a #idmef_alert_t object.
 * @source_cur: pointer to a #idmef_source_t object.
 *
 * Get the next #idmef_source_t object listed in @ptr.
 * When iterating over the idmef_source_t object listed in @ptr,
 * @object should be set to the latest returned #idmef_source_t object.
 *
 * Returns: the next #idmef_source_t in the list.
 */
idmef_source_t *idmef_alert_get_next_source(idmef_alert_t *alert, idmef_source_t *source_cur)
{
        prelude_list_t *tmp = (source_cur) ? &((prelude_linked_object_t *) source_cur)->_list : NULL;

        prelude_return_val_if_fail(alert, NULL);

        prelude_list_for_each_continue(&alert->source_list, tmp)
                return prelude_linked_object_get_object(tmp);

        return NULL;
}


/**
 * idmef_alert_set_source:
 * @ptr: pointer to a #idmef_alert_t object.
 * @object: pointer to a #idmef_source_t object.
 * @pos: Position in the list.
 *
 * Add @object to position @pos of @ptr list of #idmef_source_t object.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 */
void idmef_alert_set_source(idmef_alert_t *ptr, idmef_source_t *object, int pos)
{
        prelude_return_if_fail(ptr);
        prelude_return_if_fail(object);

        if ( ! prelude_list_is_empty(&((prelude_linked_object_t *) object)->_list) )
                prelude_list_del_init(&((prelude_linked_object_t *) object)->_list);

        list_insert(&ptr->source_list, &((prelude_linked_object_t *) object)->_list, pos);
}


/**
 * idmef_alert_new_source:
 * @ptr: pointer to a #idmef_alert_t object.
 * @ret: pointer to an address where to store the created #idmef_source_t object.
 * @pos: position in the list.
 *
 * Create a new #idmef_source_t children of @ptr, and add it to position @pos of
 * @ptr list of #idmef_source_t object. The created #idmef_source_t object is
 * stored in @ret.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_alert_new_source(idmef_alert_t *ptr, idmef_source_t **ret, int pos)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        retval = idmef_source_new(ret);
        if ( retval < 0 )
                return retval;

        list_insert(&ptr->source_list, &((prelude_linked_object_t *)(*ret))->_list, pos);

        return 0;
}


/**
 * idmef_alert_get_next_target:
 * @alert: pointer to a #idmef_alert_t object.
 * @target_cur: pointer to a #idmef_target_t object.
 *
 * Get the next #idmef_target_t object listed in @ptr.
 * When iterating over the idmef_target_t object listed in @ptr,
 * @object should be set to the latest returned #idmef_target_t object.
 *
 * Returns: the next #idmef_target_t in the list.
 */
idmef_target_t *idmef_alert_get_next_target(idmef_alert_t *alert, idmef_target_t *target_cur)
{
        prelude_list_t *tmp = (target_cur) ? &((prelude_linked_object_t *) target_cur)->_list : NULL;

        prelude_return_val_if_fail(alert, NULL);

        prelude_list_for_each_continue(&alert->target_list, tmp)
                return prelude_linked_object_get_object(tmp);

        return NULL;
}


/**
 * idmef_alert_set_target:
 * @ptr: pointer to a #idmef_alert_t object.
 * @object: pointer to a #idmef_target_t object.
 * @pos: Position in the list.
 *
 * Add @object to position @pos of @ptr list of #idmef_target_t object.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 */
void idmef_alert_set_target(idmef_alert_t *ptr, idmef_target_t *object, int pos)
{
        prelude_return_if_fail(ptr);
        prelude_return_if_fail(object);

        if ( ! prelude_list_is_empty(&((prelude_linked_object_t *) object)->_list) )
                prelude_list_del_init(&((prelude_linked_object_t *) object)->_list);

        list_insert(&ptr->target_list, &((prelude_linked_object_t *) object)->_list, pos);
}


/**
 * idmef_alert_new_target:
 * @ptr: pointer to a #idmef_alert_t object.
 * @ret: pointer to an address where to store the created #idmef_target_t object.
 * @pos: position in the list.
 *
 * Create a new #idmef_target_t children of @ptr, and add it to position @pos of
 * @ptr list of #idmef_target_t object. The created #idmef_target_t object is
 * stored in @ret.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_alert_new_target(idmef_alert_t *ptr, idmef_target_t **ret, int pos)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        retval = idmef_target_new(ret);
        if ( retval < 0 )
                return retval;

        list_insert(&ptr->target_list, &((prelude_linked_object_t *)(*ret))->_list, pos);

        return 0;
}


/**
 * idmef_alert_get_assessment:
 * @ptr: pointer to a #idmef_alert_t object.
 *
 * Get assessment children of the #idmef_alert_t object.
 *
 * Returns: a pointer to a idmef_assessment_t object, or NULL if the children object is not set.
 */
idmef_assessment_t *idmef_alert_get_assessment(idmef_alert_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->assessment;
}

/**
 * idmef_alert_set_assessment:
 * @ptr: pointer to a #idmef_alert_t object.
 * @assessment: pointer to a #idmef_assessment_t object.
 *
 * Set @assessment object as a children of @ptr.
 * if @ptr already contain an @assessment object, then it is destroyed,
 * and updated to point to the provided @assessment object.
 */

void idmef_alert_set_assessment(idmef_alert_t *ptr, idmef_assessment_t *assessment)
{
        prelude_return_if_fail(ptr);

        if ( ptr->assessment )
                idmef_assessment_destroy(ptr->assessment);

        ptr->assessment = assessment;
}

/**
 * idmef_alert_new_assessment:
 * @ptr: pointer to a #idmef_alert_t object.
 * @ret: pointer to an address where to store the created #idmef_assessment_t object.
 *
 * Create a new assessment object, children of #idmef_alert_t.
 * If @ptr already contain a #idmef_assessment_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_alert_new_assessment(idmef_alert_t *ptr, idmef_assessment_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->assessment ) {
                retval = idmef_assessment_new(&ptr->assessment);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->assessment;
        return 0;
}

/**
 * idmef_alert_get_next_additional_data:
 * @alert: pointer to a #idmef_alert_t object.
 * @additional_data_cur: pointer to a #idmef_additional_data_t object.
 *
 * Get the next #idmef_additional_data_t object listed in @ptr.
 * When iterating over the idmef_additional_data_t object listed in @ptr,
 * @object should be set to the latest returned #idmef_additional_data_t object.
 *
 * Returns: the next #idmef_additional_data_t in the list.
 */
idmef_additional_data_t *idmef_alert_get_next_additional_data(idmef_alert_t *alert, idmef_additional_data_t *additional_data_cur)
{
        prelude_list_t *tmp = (additional_data_cur) ? &((prelude_linked_object_t *) additional_data_cur)->_list : NULL;

        prelude_return_val_if_fail(alert, NULL);

        prelude_list_for_each_continue(&alert->additional_data_list, tmp)
                return prelude_linked_object_get_object(tmp);

        return NULL;
}


/**
 * idmef_alert_set_additional_data:
 * @ptr: pointer to a #idmef_alert_t object.
 * @object: pointer to a #idmef_additional_data_t object.
 * @pos: Position in the list.
 *
 * Add @object to position @pos of @ptr list of #idmef_additional_data_t object.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 */
void idmef_alert_set_additional_data(idmef_alert_t *ptr, idmef_additional_data_t *object, int pos)
{
        prelude_return_if_fail(ptr);
        prelude_return_if_fail(object);

        if ( ! prelude_list_is_empty(&((prelude_linked_object_t *) object)->_list) )
                prelude_list_del_init(&((prelude_linked_object_t *) object)->_list);

        list_insert(&ptr->additional_data_list, &((prelude_linked_object_t *) object)->_list, pos);
}


/**
 * idmef_alert_new_additional_data:
 * @ptr: pointer to a #idmef_alert_t object.
 * @ret: pointer to an address where to store the created #idmef_additional_data_t object.
 * @pos: position in the list.
 *
 * Create a new #idmef_additional_data_t children of @ptr, and add it to position @pos of
 * @ptr list of #idmef_additional_data_t object. The created #idmef_additional_data_t object is
 * stored in @ret.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_alert_new_additional_data(idmef_alert_t *ptr, idmef_additional_data_t **ret, int pos)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        retval = idmef_additional_data_new(ret);
        if ( retval < 0 )
                return retval;

        list_insert(&ptr->additional_data_list, &((prelude_linked_object_t *)(*ret))->_list, pos);

        return 0;
}


/**
 * idmef_alert_get_type:
 * @ptr: pointer to a #idmef_alert_t object.
 *
 * Access the type children of @ptr.
 *
 * Returns: a pointer to the #idmef_alert_type_t children, or NULL if it is not set.
 */
idmef_alert_type_t idmef_alert_get_type(idmef_alert_t *ptr)
{
        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));
        return ptr->type;
}

/**
 * idmef_alert_get_tool_alert:
 * @ptr: pointer to a #idmef_alert_t object.
 *
 * Access the tool_alert children of @ptr.
 *
 * Returns: a pointer to the #idmef_tool_alert_t children, or NULL if it is not set.
 */
idmef_tool_alert_t *idmef_alert_get_tool_alert(idmef_alert_t *ptr)
{
        prelude_return_val_if_fail(ptr, NULL);
        return (ptr->type == IDMEF_ALERT_TYPE_TOOL) ? ptr->detail.tool_alert : NULL;
}

/**
 * idmef_alert_set_tool_alert:
 * @ptr: pointer to a #idmef_alert_t object.
 * @tool_alert: pointer to a #idmef_tool_alert_t object.
 *
 * Set @tool_alert object as a children of @ptr.
 * if @ptr already contain a @tool_alert object, then it is destroyed,
 * and updated to point to the provided @tool_alert object.
 */
void idmef_alert_set_tool_alert(idmef_alert_t *ptr, idmef_tool_alert_t *tool_alert)
{
        prelude_return_if_fail(ptr);

        switch ( ptr->type ) {

                case IDMEF_ALERT_TYPE_TOOL:
                        idmef_tool_alert_destroy(ptr->detail.tool_alert);
                        break;

                case IDMEF_ALERT_TYPE_CORRELATION:
                        idmef_correlation_alert_destroy(ptr->detail.correlation_alert);
                        break;

                case IDMEF_ALERT_TYPE_OVERFLOW:
                        idmef_overflow_alert_destroy(ptr->detail.overflow_alert);
                        break;

                default:
                        break;
        }

        ptr->detail.tool_alert = tool_alert;
        ptr->type = (tool_alert) ? IDMEF_ALERT_TYPE_TOOL : 0;
}

/**
 * idmef_alert_new_tool_alert:
 * @ptr: pointer to a #idmef_alert_t object.
 * @ret: pointer where to store the created #idmef_tool_alert_t object.
 *
 * Create a new idmef_tool_alert_t object, children of #idmef_alert_t.
 * If @ptr already contain a #idmef_tool_alert_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_alert_new_tool_alert(idmef_alert_t *ptr, idmef_tool_alert_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( ptr->type ) {

                case IDMEF_ALERT_TYPE_TOOL:
                        *ret = ptr->detail.tool_alert;
                        return 0;

                case IDMEF_ALERT_TYPE_CORRELATION:
                        idmef_correlation_alert_destroy(ptr->detail.correlation_alert);
                        break;

                case IDMEF_ALERT_TYPE_OVERFLOW:
                        idmef_overflow_alert_destroy(ptr->detail.overflow_alert);
                        break;

                default:
                        break;
        }

        retval = idmef_tool_alert_new(ret);
        if ( retval < 0 )
                return retval;

        ptr->type = IDMEF_ALERT_TYPE_TOOL;
        ptr->detail.tool_alert = *ret;

        return 0;
}

/**
 * idmef_alert_get_correlation_alert:
 * @ptr: pointer to a #idmef_alert_t object.
 *
 * Access the correlation_alert children of @ptr.
 *
 * Returns: a pointer to the #idmef_correlation_alert_t children, or NULL if it is not set.
 */
idmef_correlation_alert_t *idmef_alert_get_correlation_alert(idmef_alert_t *ptr)
{
        prelude_return_val_if_fail(ptr, NULL);
        return (ptr->type == IDMEF_ALERT_TYPE_CORRELATION) ? ptr->detail.correlation_alert : NULL;
}

/**
 * idmef_alert_set_correlation_alert:
 * @ptr: pointer to a #idmef_alert_t object.
 * @correlation_alert: pointer to a #idmef_correlation_alert_t object.
 *
 * Set @correlation_alert object as a children of @ptr.
 * if @ptr already contain a @correlation_alert object, then it is destroyed,
 * and updated to point to the provided @correlation_alert object.
 */
void idmef_alert_set_correlation_alert(idmef_alert_t *ptr, idmef_correlation_alert_t *correlation_alert)
{
        prelude_return_if_fail(ptr);

        switch ( ptr->type ) {

                case IDMEF_ALERT_TYPE_TOOL:
                        idmef_tool_alert_destroy(ptr->detail.tool_alert);
                        break;

                case IDMEF_ALERT_TYPE_CORRELATION:
                        idmef_correlation_alert_destroy(ptr->detail.correlation_alert);
                        break;

                case IDMEF_ALERT_TYPE_OVERFLOW:
                        idmef_overflow_alert_destroy(ptr->detail.overflow_alert);
                        break;

                default:
                        break;
        }

        ptr->detail.correlation_alert = correlation_alert;
        ptr->type = (correlation_alert) ? IDMEF_ALERT_TYPE_CORRELATION : 0;
}

/**
 * idmef_alert_new_correlation_alert:
 * @ptr: pointer to a #idmef_alert_t object.
 * @ret: pointer where to store the created #idmef_correlation_alert_t object.
 *
 * Create a new idmef_correlation_alert_t object, children of #idmef_alert_t.
 * If @ptr already contain a #idmef_correlation_alert_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_alert_new_correlation_alert(idmef_alert_t *ptr, idmef_correlation_alert_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( ptr->type ) {

                case IDMEF_ALERT_TYPE_TOOL:
                        idmef_tool_alert_destroy(ptr->detail.tool_alert);
                        break;

                case IDMEF_ALERT_TYPE_CORRELATION:
                        *ret = ptr->detail.correlation_alert;
                        return 0;

                case IDMEF_ALERT_TYPE_OVERFLOW:
                        idmef_overflow_alert_destroy(ptr->detail.overflow_alert);
                        break;

                default:
                        break;
        }

        retval = idmef_correlation_alert_new(ret);
        if ( retval < 0 )
                return retval;

        ptr->type = IDMEF_ALERT_TYPE_CORRELATION;
        ptr->detail.correlation_alert = *ret;

        return 0;
}

/**
 * idmef_alert_get_overflow_alert:
 * @ptr: pointer to a #idmef_alert_t object.
 *
 * Access the overflow_alert children of @ptr.
 *
 * Returns: a pointer to the #idmef_overflow_alert_t children, or NULL if it is not set.
 */
idmef_overflow_alert_t *idmef_alert_get_overflow_alert(idmef_alert_t *ptr)
{
        prelude_return_val_if_fail(ptr, NULL);
        return (ptr->type == IDMEF_ALERT_TYPE_OVERFLOW) ? ptr->detail.overflow_alert : NULL;
}

/**
 * idmef_alert_set_overflow_alert:
 * @ptr: pointer to a #idmef_alert_t object.
 * @overflow_alert: pointer to a #idmef_overflow_alert_t object.
 *
 * Set @overflow_alert object as a children of @ptr.
 * if @ptr already contain a @overflow_alert object, then it is destroyed,
 * and updated to point to the provided @overflow_alert object.
 */
void idmef_alert_set_overflow_alert(idmef_alert_t *ptr, idmef_overflow_alert_t *overflow_alert)
{
        prelude_return_if_fail(ptr);

        switch ( ptr->type ) {

                case IDMEF_ALERT_TYPE_TOOL:
                        idmef_tool_alert_destroy(ptr->detail.tool_alert);
                        break;

                case IDMEF_ALERT_TYPE_CORRELATION:
                        idmef_correlation_alert_destroy(ptr->detail.correlation_alert);
                        break;

                case IDMEF_ALERT_TYPE_OVERFLOW:
                        idmef_overflow_alert_destroy(ptr->detail.overflow_alert);
                        break;

                default:
                        break;
        }

        ptr->detail.overflow_alert = overflow_alert;
        ptr->type = (overflow_alert) ? IDMEF_ALERT_TYPE_OVERFLOW : 0;
}

/**
 * idmef_alert_new_overflow_alert:
 * @ptr: pointer to a #idmef_alert_t object.
 * @ret: pointer where to store the created #idmef_overflow_alert_t object.
 *
 * Create a new idmef_overflow_alert_t object, children of #idmef_alert_t.
 * If @ptr already contain a #idmef_overflow_alert_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_alert_new_overflow_alert(idmef_alert_t *ptr, idmef_overflow_alert_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( ptr->type ) {

                case IDMEF_ALERT_TYPE_TOOL:
                        idmef_tool_alert_destroy(ptr->detail.tool_alert);
                        break;

                case IDMEF_ALERT_TYPE_CORRELATION:
                        idmef_correlation_alert_destroy(ptr->detail.correlation_alert);
                        break;

                case IDMEF_ALERT_TYPE_OVERFLOW:
                        *ret = ptr->detail.overflow_alert;
                        return 0;

                default:
                        break;
        }

        retval = idmef_overflow_alert_new(ret);
        if ( retval < 0 )
                return retval;

        ptr->type = IDMEF_ALERT_TYPE_OVERFLOW;
        ptr->detail.overflow_alert = *ret;

        return 0;
}

/**
 * idmef_alert_copy:
 * @src: Source of the copy.
 * @dst: Where to copy the object.
 *
 * Copy a new #idmef_alert_t object from @src to @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_alert_copy(const idmef_alert_t *src, idmef_alert_t *dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));
        prelude_return_val_if_fail(dst, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = 0;

        if ( dst->messageid ) {
                prelude_string_destroy(dst->messageid);
                dst->messageid = NULL;
        }

        if ( src->messageid ) {
                ret = prelude_string_clone(src->messageid, &dst->messageid);
                if ( ret < 0 )
                        return ret;
        }

        {
                prelude_list_t *n, *tmp;
                idmef_analyzer_t *entry, *new;

                prelude_list_for_each_safe(&dst->analyzer_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        idmef_analyzer_destroy(entry);
                }

                prelude_list_for_each_safe(&src->analyzer_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        idmef_analyzer_clone(entry, &new);
                        prelude_list_add_tail(&dst->analyzer_list, &((prelude_linked_object_t *) new)->_list);
                }
        }

        if ( src->create_time ) {
                ret = idmef_time_copy(src->create_time, dst->create_time);
                if ( ret < 0 )
                        return ret;
        }

        if ( src->classification ) {
                ret = idmef_classification_copy(src->classification, dst->classification);
                if ( ret < 0 )
                        return ret;
        }

        if ( dst->detect_time ) {
                idmef_time_destroy(dst->detect_time);
                dst->detect_time = NULL;
        }

        if ( src->detect_time ) {
                ret = idmef_time_clone(src->detect_time, &dst->detect_time);
                if ( ret < 0 )
                        return ret;
        }

        if ( dst->analyzer_time ) {
                idmef_time_destroy(dst->analyzer_time);
                dst->analyzer_time = NULL;
        }

        if ( src->analyzer_time ) {
                ret = idmef_time_clone(src->analyzer_time, &dst->analyzer_time);
                if ( ret < 0 )
                        return ret;
        }

        {
                prelude_list_t *n, *tmp;
                idmef_source_t *entry, *new;

                prelude_list_for_each_safe(&dst->source_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        idmef_source_destroy(entry);
                }

                prelude_list_for_each_safe(&src->source_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        idmef_source_clone(entry, &new);
                        prelude_list_add_tail(&dst->source_list, &((prelude_linked_object_t *) new)->_list);
                }
        }

        {
                prelude_list_t *n, *tmp;
                idmef_target_t *entry, *new;

                prelude_list_for_each_safe(&dst->target_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        idmef_target_destroy(entry);
                }

                prelude_list_for_each_safe(&src->target_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        idmef_target_clone(entry, &new);
                        prelude_list_add_tail(&dst->target_list, &((prelude_linked_object_t *) new)->_list);
                }
        }

        if ( dst->assessment ) {
                idmef_assessment_destroy(dst->assessment);
                dst->assessment = NULL;
        }

        if ( src->assessment ) {
                ret = idmef_assessment_clone(src->assessment, &dst->assessment);
                if ( ret < 0 )
                        return ret;
        }

        {
                prelude_list_t *n, *tmp;
                idmef_additional_data_t *entry, *new;

                prelude_list_for_each_safe(&dst->additional_data_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        idmef_additional_data_destroy(entry);
                }

                prelude_list_for_each_safe(&src->additional_data_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        idmef_additional_data_clone(entry, &new);
                        prelude_list_add_tail(&dst->additional_data_list, &((prelude_linked_object_t *) new)->_list);
                }
        }

        switch ( dst->type ) {

                case IDMEF_ALERT_TYPE_TOOL:
                        idmef_tool_alert_destroy(dst->detail.tool_alert);
                        break;

                case IDMEF_ALERT_TYPE_CORRELATION:
                        idmef_correlation_alert_destroy(dst->detail.correlation_alert);
                        break;

                case IDMEF_ALERT_TYPE_OVERFLOW:
                        idmef_overflow_alert_destroy(dst->detail.overflow_alert);
                        break;

                default:
                        break;
        }

        switch ( src->type ) {

                case IDMEF_ALERT_TYPE_TOOL:
                        ret = idmef_tool_alert_clone(src->detail.tool_alert, &dst->detail.tool_alert);
                        break;

                case IDMEF_ALERT_TYPE_CORRELATION:
                        ret = idmef_correlation_alert_clone(src->detail.correlation_alert, &dst->detail.correlation_alert);
                        break;

                case IDMEF_ALERT_TYPE_OVERFLOW:
                        ret = idmef_overflow_alert_clone(src->detail.overflow_alert, &dst->detail.overflow_alert);
                        break;

                default:
                        break;
        }

        if ( ret < 0 )
               return ret;

        dst->type = src->type;

        return 0;
}

/**
 * idmef_alert_clone:
 * @src: Object to be cloned.
 * @dst: Address where to store the pointer to the cloned object.
 *
 * Create a copy of @src, and store it in @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_alert_clone(idmef_alert_t *src, idmef_alert_t **dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = idmef_alert_new(dst);
        if ( ret < 0 )
                return ret;

        return idmef_alert_copy(src, *dst);
}

/**
 * idmef_alert_compare:
 * @obj1: Object to compare with @obj2.
 * @obj2: Object to compare with @obj1.
 *
 * Compare @obj1 with @obj2.
 *
 * Returns: 0 on match, a negative value on comparison failure.
 */
int idmef_alert_compare(const idmef_alert_t *obj1, const idmef_alert_t *obj2)
{
        int ret = 0;

        if ( obj1 == NULL && obj2 == NULL )
                return 0;

        else if ( obj1 == NULL || obj2 == NULL )
                return -1;

        ret = prelude_string_compare(obj1->messageid, obj2->messageid);
        if ( ret != 0 )
                return ret;

        {
                prelude_list_t *tmp1, *tmp2;
                idmef_analyzer_t *entry1, *entry2;

                tmp1 = tmp2 = NULL;
                do {
                        entry1 = entry2 = NULL;

                        prelude_list_for_each_continue(&obj1->analyzer_list, tmp1) {
                                entry1 = prelude_linked_object_get_object(tmp1);
                                break;
                        }

                        prelude_list_for_each_continue(&obj2->analyzer_list, tmp2) {
                                entry2 = prelude_linked_object_get_object(tmp2);
                                break;
                        }

                        ret = idmef_analyzer_compare(entry1, entry2);
                        if ( ret != 0 )
                                return ret;

                } while ( entry1 && entry2 );
        }

        ret = idmef_time_compare(obj1->create_time, obj2->create_time);
        if ( ret != 0 )
                return ret;

        ret = idmef_classification_compare(obj1->classification, obj2->classification);
        if ( ret != 0 )
                return ret;

        ret = idmef_time_compare(obj1->detect_time, obj2->detect_time);
        if ( ret != 0 )
                return ret;

        ret = idmef_time_compare(obj1->analyzer_time, obj2->analyzer_time);
        if ( ret != 0 )
                return ret;

        {
                prelude_list_t *tmp1, *tmp2;
                idmef_source_t *entry1, *entry2;

                tmp1 = tmp2 = NULL;
                do {
                        entry1 = entry2 = NULL;

                        prelude_list_for_each_continue(&obj1->source_list, tmp1) {
                                entry1 = prelude_linked_object_get_object(tmp1);
                                break;
                        }

                        prelude_list_for_each_continue(&obj2->source_list, tmp2) {
                                entry2 = prelude_linked_object_get_object(tmp2);
                                break;
                        }

                        ret = idmef_source_compare(entry1, entry2);
                        if ( ret != 0 )
                                return ret;

                } while ( entry1 && entry2 );
        }

        {
                prelude_list_t *tmp1, *tmp2;
                idmef_target_t *entry1, *entry2;

                tmp1 = tmp2 = NULL;
                do {
                        entry1 = entry2 = NULL;

                        prelude_list_for_each_continue(&obj1->target_list, tmp1) {
                                entry1 = prelude_linked_object_get_object(tmp1);
                                break;
                        }

                        prelude_list_for_each_continue(&obj2->target_list, tmp2) {
                                entry2 = prelude_linked_object_get_object(tmp2);
                                break;
                        }

                        ret = idmef_target_compare(entry1, entry2);
                        if ( ret != 0 )
                                return ret;

                } while ( entry1 && entry2 );
        }

        ret = idmef_assessment_compare(obj1->assessment, obj2->assessment);
        if ( ret != 0 )
                return ret;

        {
                prelude_list_t *tmp1, *tmp2;
                idmef_additional_data_t *entry1, *entry2;

                tmp1 = tmp2 = NULL;
                do {
                        entry1 = entry2 = NULL;

                        prelude_list_for_each_continue(&obj1->additional_data_list, tmp1) {
                                entry1 = prelude_linked_object_get_object(tmp1);
                                break;
                        }

                        prelude_list_for_each_continue(&obj2->additional_data_list, tmp2) {
                                entry2 = prelude_linked_object_get_object(tmp2);
                                break;
                        }

                        ret = idmef_additional_data_compare(entry1, entry2);
                        if ( ret != 0 )
                                return ret;

                } while ( entry1 && entry2 );
        }

        if ( obj1->type != obj2->type )
                return -1;

        switch ( obj1->type ) {

                case IDMEF_ALERT_TYPE_TOOL:
                        ret = idmef_tool_alert_compare(obj1->detail.tool_alert, obj2->detail.tool_alert);
                        break;

                case IDMEF_ALERT_TYPE_CORRELATION:
                        ret = idmef_correlation_alert_compare(obj1->detail.correlation_alert, obj2->detail.correlation_alert);
                        break;

                case IDMEF_ALERT_TYPE_OVERFLOW:
                        ret = idmef_overflow_alert_compare(obj1->detail.overflow_alert, obj2->detail.overflow_alert);
                        break;

                default:
                        break;
        }

        return ret;
}

/**
 * idmef_heartbeat_new:
 * @ret: Pointer where to store the created #idmef_heartbeat_t object.
 *
 * Create a new #idmef_heartbeat_t object.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_heartbeat_new(idmef_heartbeat_t **ret)
{
        *ret = calloc(1, sizeof(**ret));
        if ( ! *ret )
                return prelude_error_from_errno(errno);

        (*ret)->_idmef_object_id = IDMEF_CLASS_ID_HEARTBEAT;

        (*ret)->refcount = 1;

        prelude_list_init(&(*ret)->analyzer_list);


        prelude_list_init(&(*ret)->additional_data_list);


        {
                int retval = idmef_time_new(&(*ret)->create_time);

                if ( retval < 0 ) {
                        idmef_heartbeat_destroy(*ret);
                        *ret = NULL;
                        return retval;
                }
        }

        idmef_time_set_from_gettimeofday((*ret)->create_time);

        return 0;

}

/**
 * idmef_heartbeat_ref:
 * @heartbeat: pointer to a #idmef_heartbeat_t object.
 *
 * Increase @heartbeat reference count, so that it can be referenced
 * multiple time.
 *
 * Returns: a pointer to @heartbeat.
 */
idmef_heartbeat_t *idmef_heartbeat_ref(idmef_heartbeat_t *heartbeat)
{
        prelude_return_val_if_fail(heartbeat, NULL);
        heartbeat->refcount++;

        return heartbeat;
}

int _idmef_heartbeat_get_child(void *p, idmef_class_child_id_t child, void **childptr)
{
        idmef_heartbeat_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));
        *childptr = NULL;

        switch ( child ) {

                case 0:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->messageid, TRUE);
                case 1:
                        *childptr = &ptr->analyzer_list;
                        return 0;

                case 2:
                       return get_value_from_time((idmef_value_t **) childptr,  ptr->create_time, TRUE);
                case 3:
                       return get_value_from_time((idmef_value_t **) childptr,  ptr->analyzer_time, TRUE);
                case 4:
                       return (ptr->heartbeat_interval_is_set) ? idmef_value_new_uint32((idmef_value_t **) childptr, ptr->heartbeat_interval) : 0;

                case 5:
                        *childptr = &ptr->additional_data_list;
                        return 0;

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_heartbeat_new_child(void *p, idmef_class_child_id_t child, int n, void **ret)
{
        idmef_heartbeat_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        return idmef_heartbeat_new_messageid(ptr, (prelude_string_t **) ret);

                case 1: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n == IDMEF_LIST_APPEND || n == IDMEF_LIST_PREPEND )
                               return idmef_heartbeat_new_analyzer(ptr, (idmef_analyzer_t **) ret, n);

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->analyzer_list, tmp) {
                                       if ( i++ == n ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->analyzer_list, tmp) {
                                       if ( i++ == pos ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }

                        return idmef_heartbeat_new_analyzer(ptr, (idmef_analyzer_t **) ret, n);
                }

                case 2:
                        return idmef_heartbeat_new_create_time(ptr, (idmef_time_t **) ret);

                case 3:
                        return idmef_heartbeat_new_analyzer_time(ptr, (idmef_time_t **) ret);

                case 4:
                        return idmef_heartbeat_new_heartbeat_interval(ptr, (uint32_t **) ret);

                case 5: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n == IDMEF_LIST_APPEND || n == IDMEF_LIST_PREPEND )
                               return idmef_heartbeat_new_additional_data(ptr, (idmef_additional_data_t **) ret, n);

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->additional_data_list, tmp) {
                                       if ( i++ == n ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->additional_data_list, tmp) {
                                       if ( i++ == pos ) {
                                               *ret = prelude_linked_object_get_object(tmp);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }

                        return idmef_heartbeat_new_additional_data(ptr, (idmef_additional_data_t **) ret, n);
                }

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_heartbeat_destroy_child(void *p, idmef_class_child_id_t child, int n)
{
        idmef_heartbeat_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        if ( ptr->messageid ) {
                                prelude_string_destroy(ptr->messageid);
                                ptr->messageid = NULL;
                        }

                        return 0;

                case 1: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->analyzer_list, tmp) {
                                       if ( i++ == n ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               idmef_analyzer_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->analyzer_list, tmp) {
                                       if ( i++ == pos ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               idmef_analyzer_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }
                }

                case 2:
                        if ( ptr->create_time ) {
                                idmef_time_destroy(ptr->create_time);
                                ptr->create_time = NULL;
                        }

                        return 0;

                case 3:
                        if ( ptr->analyzer_time ) {
                                idmef_time_destroy(ptr->analyzer_time);
                                ptr->analyzer_time = NULL;
                        }

                        return 0;

                case 4:
                        ptr->heartbeat_interval_is_set = 0;
                        return 0;

                case 5: {
                        int i = 0;
                        prelude_list_t *tmp;

                        if ( n >= 0 ) {
                               prelude_list_for_each(&ptr->additional_data_list, tmp) {
                                       if ( i++ == n ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               idmef_additional_data_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != n )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        } else {
                               int pos = (-n) - 1; /* With negative value, -1 is the base, translate to 0 */

                               prelude_list_for_each_reversed(&ptr->additional_data_list, tmp) {
                                       if ( i++ == pos ) {
                                               void *b = prelude_linked_object_get_object(tmp);
                                               idmef_additional_data_destroy(b);
                                               return 0;
                                       }
                               }

                               if ( i != pos )
                                       return prelude_error(PRELUDE_ERROR_IDMEF_TREE_INDEX_UNDEFINED);
                        }
                }

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

static void idmef_heartbeat_destroy_internal(idmef_heartbeat_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( ptr->messageid ) {
                prelude_string_destroy(ptr->messageid);
                ptr->messageid = NULL;
        }

        {
                prelude_list_t *n, *tmp;
                idmef_analyzer_t *entry;

                prelude_list_for_each_safe(&ptr->analyzer_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        prelude_list_del_init(tmp);
                        idmef_analyzer_destroy(entry);
                }
        }

        if ( ptr->create_time ) {
                idmef_time_destroy(ptr->create_time);
                ptr->create_time = NULL;
        }

        if ( ptr->analyzer_time ) {
                idmef_time_destroy(ptr->analyzer_time);
                ptr->analyzer_time = NULL;
        }

        {
                prelude_list_t *n, *tmp;
                idmef_additional_data_t *entry;

                prelude_list_for_each_safe(&ptr->additional_data_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        prelude_list_del_init(tmp);
                        idmef_additional_data_destroy(entry);
                }
        }


        /* free() should be done by the caller */
}

/**
 * idmef_heartbeat_destroy:
 * @ptr: pointer to a #idmef_heartbeat_t object.
 *
 * Destroy @ptr and all of it's children.
 * The objects are only destroyed if their reference count reach zero.
 */

void idmef_heartbeat_destroy(idmef_heartbeat_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( --ptr->refcount )
                return;

        idmef_heartbeat_destroy_internal(ptr);
        free(ptr);
}

/**
 * idmef_heartbeat_get_messageid:
 * @ptr: pointer to a #idmef_heartbeat_t object.
 *
 * Get messageid children of the #idmef_heartbeat_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_heartbeat_get_messageid(idmef_heartbeat_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->messageid;
}

/**
 * idmef_heartbeat_set_messageid:
 * @ptr: pointer to a #idmef_heartbeat_t object.
 * @messageid: pointer to a #prelude_string_t object.
 *
 * Set @messageid object as a children of @ptr.
 * if @ptr already contain an @messageid object, then it is destroyed,
 * and updated to point to the provided @messageid object.
 */

void idmef_heartbeat_set_messageid(idmef_heartbeat_t *ptr, prelude_string_t *messageid)
{
        prelude_return_if_fail(ptr);

        if ( ptr->messageid )
                prelude_string_destroy(ptr->messageid);

        ptr->messageid = messageid;
}

/**
 * idmef_heartbeat_new_messageid:
 * @ptr: pointer to a #idmef_heartbeat_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new messageid object, children of #idmef_heartbeat_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_heartbeat_new_messageid(idmef_heartbeat_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->messageid ) {
                retval = prelude_string_new(&ptr->messageid);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->messageid;
        return 0;
}

/**
 * idmef_heartbeat_get_next_analyzer:
 * @heartbeat: pointer to a #idmef_heartbeat_t object.
 * @analyzer_cur: pointer to a #idmef_analyzer_t object.
 *
 * Get the next #idmef_analyzer_t object listed in @ptr.
 * When iterating over the idmef_analyzer_t object listed in @ptr,
 * @object should be set to the latest returned #idmef_analyzer_t object.
 *
 * Returns: the next #idmef_analyzer_t in the list.
 */
idmef_analyzer_t *idmef_heartbeat_get_next_analyzer(idmef_heartbeat_t *heartbeat, idmef_analyzer_t *analyzer_cur)
{
        prelude_list_t *tmp = (analyzer_cur) ? &((prelude_linked_object_t *) analyzer_cur)->_list : NULL;

        prelude_return_val_if_fail(heartbeat, NULL);

        prelude_list_for_each_continue(&heartbeat->analyzer_list, tmp)
                return prelude_linked_object_get_object(tmp);

        return NULL;
}


/**
 * idmef_heartbeat_set_analyzer:
 * @ptr: pointer to a #idmef_heartbeat_t object.
 * @object: pointer to a #idmef_analyzer_t object.
 * @pos: Position in the list.
 *
 * Add @object to position @pos of @ptr list of #idmef_analyzer_t object.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 */
void idmef_heartbeat_set_analyzer(idmef_heartbeat_t *ptr, idmef_analyzer_t *object, int pos)
{
        prelude_return_if_fail(ptr);
        prelude_return_if_fail(object);

        if ( ! prelude_list_is_empty(&((prelude_linked_object_t *) object)->_list) )
                prelude_list_del_init(&((prelude_linked_object_t *) object)->_list);

        list_insert(&ptr->analyzer_list, &((prelude_linked_object_t *) object)->_list, pos);
}


/**
 * idmef_heartbeat_new_analyzer:
 * @ptr: pointer to a #idmef_heartbeat_t object.
 * @ret: pointer to an address where to store the created #idmef_analyzer_t object.
 * @pos: position in the list.
 *
 * Create a new #idmef_analyzer_t children of @ptr, and add it to position @pos of
 * @ptr list of #idmef_analyzer_t object. The created #idmef_analyzer_t object is
 * stored in @ret.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_heartbeat_new_analyzer(idmef_heartbeat_t *ptr, idmef_analyzer_t **ret, int pos)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        retval = idmef_analyzer_new(ret);
        if ( retval < 0 )
                return retval;

        list_insert(&ptr->analyzer_list, &((prelude_linked_object_t *)(*ret))->_list, pos);

        return 0;
}


/**
 * idmef_heartbeat_get_create_time:
 * @ptr: pointer to a #idmef_heartbeat_t object.
 *
 * Get create_time children of the #idmef_heartbeat_t object.
 *
 * Returns: a pointer to a idmef_time_t object, or NULL if the children object is not set.
 */
idmef_time_t *idmef_heartbeat_get_create_time(idmef_heartbeat_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->create_time;
}

/**
 * idmef_heartbeat_set_create_time:
 * @ptr: pointer to a #idmef_heartbeat_t object.
 * @create_time: pointer to a #idmef_time_t object.
 *
 * Set @create_time object as a children of @ptr.
 * if @ptr already contain an @create_time object, then it is destroyed,
 * and updated to point to the provided @create_time object.
 */

void idmef_heartbeat_set_create_time(idmef_heartbeat_t *ptr, idmef_time_t *create_time)
{
        prelude_return_if_fail(ptr);

        if ( ptr->create_time )
                idmef_time_destroy(ptr->create_time);

        ptr->create_time = create_time;
}

/**
 * idmef_heartbeat_new_create_time:
 * @ptr: pointer to a #idmef_heartbeat_t object.
 * @ret: pointer to an address where to store the created #idmef_time_t object.
 *
 * Create a new create_time object, children of #idmef_heartbeat_t.
 * If @ptr already contain a #idmef_time_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_heartbeat_new_create_time(idmef_heartbeat_t *ptr, idmef_time_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->create_time ) {
                retval = idmef_time_new(&ptr->create_time);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->create_time;
        return 0;
}

/**
 * idmef_heartbeat_get_analyzer_time:
 * @ptr: pointer to a #idmef_heartbeat_t object.
 *
 * Get analyzer_time children of the #idmef_heartbeat_t object.
 *
 * Returns: a pointer to a idmef_time_t object, or NULL if the children object is not set.
 */
idmef_time_t *idmef_heartbeat_get_analyzer_time(idmef_heartbeat_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->analyzer_time;
}

/**
 * idmef_heartbeat_set_analyzer_time:
 * @ptr: pointer to a #idmef_heartbeat_t object.
 * @analyzer_time: pointer to a #idmef_time_t object.
 *
 * Set @analyzer_time object as a children of @ptr.
 * if @ptr already contain an @analyzer_time object, then it is destroyed,
 * and updated to point to the provided @analyzer_time object.
 */

void idmef_heartbeat_set_analyzer_time(idmef_heartbeat_t *ptr, idmef_time_t *analyzer_time)
{
        prelude_return_if_fail(ptr);

        if ( ptr->analyzer_time )
                idmef_time_destroy(ptr->analyzer_time);

        ptr->analyzer_time = analyzer_time;
}

/**
 * idmef_heartbeat_new_analyzer_time:
 * @ptr: pointer to a #idmef_heartbeat_t object.
 * @ret: pointer to an address where to store the created #idmef_time_t object.
 *
 * Create a new analyzer_time object, children of #idmef_heartbeat_t.
 * If @ptr already contain a #idmef_time_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_heartbeat_new_analyzer_time(idmef_heartbeat_t *ptr, idmef_time_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->analyzer_time ) {
                retval = idmef_time_new(&ptr->analyzer_time);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->analyzer_time;
        return 0;
}

/**
 * idmef_heartbeat_get_heartbeat_interval:
 * @ptr: pointer to a #idmef_heartbeat_t object.
 *
 * Get heartbeat_interval children of the #idmef_heartbeat_t object.
 *
 * Returns: a pointer to a uint32_t object, or NULL if the children object is not set.
 */
uint32_t *idmef_heartbeat_get_heartbeat_interval(idmef_heartbeat_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->heartbeat_interval_is_set ? &ptr->heartbeat_interval : NULL;
}

/**
 * idmef_heartbeat_set_heartbeat_interval:
 * @ptr: pointer to a #idmef_heartbeat_t object.
 * @heartbeat_interval: pointer to a #uint32_t object.
 *
 * Set @heartbeat_interval object as a children of @ptr.
 * if @ptr already contain an @heartbeat_interval object, then it is destroyed,
 * and updated to point to the provided @heartbeat_interval object.
 */

void idmef_heartbeat_set_heartbeat_interval(idmef_heartbeat_t *ptr, uint32_t heartbeat_interval)
{
        prelude_return_if_fail(ptr);
        ptr->heartbeat_interval = heartbeat_interval;
        ptr->heartbeat_interval_is_set = 1;
}


void idmef_heartbeat_unset_heartbeat_interval(idmef_heartbeat_t *ptr)
{
        prelude_return_if_fail(ptr);
        ptr->heartbeat_interval_is_set = 0;
}


/**
 * idmef_heartbeat_new_heartbeat_interval:
 * @ptr: pointer to a #idmef_heartbeat_t object.
 * @ret: pointer to an address where to store the created #uint32_t object.
 *
 * Create a new heartbeat_interval object, children of #idmef_heartbeat_t.
 * If @ptr already contain a #uint32_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_heartbeat_new_heartbeat_interval(idmef_heartbeat_t *ptr, uint32_t **ret)
{
        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));
        ptr->heartbeat_interval_is_set = 1;

        *ret = &ptr->heartbeat_interval;
        return 0;
}

/**
 * idmef_heartbeat_get_next_additional_data:
 * @heartbeat: pointer to a #idmef_heartbeat_t object.
 * @additional_data_cur: pointer to a #idmef_additional_data_t object.
 *
 * Get the next #idmef_additional_data_t object listed in @ptr.
 * When iterating over the idmef_additional_data_t object listed in @ptr,
 * @object should be set to the latest returned #idmef_additional_data_t object.
 *
 * Returns: the next #idmef_additional_data_t in the list.
 */
idmef_additional_data_t *idmef_heartbeat_get_next_additional_data(idmef_heartbeat_t *heartbeat, idmef_additional_data_t *additional_data_cur)
{
        prelude_list_t *tmp = (additional_data_cur) ? &((prelude_linked_object_t *) additional_data_cur)->_list : NULL;

        prelude_return_val_if_fail(heartbeat, NULL);

        prelude_list_for_each_continue(&heartbeat->additional_data_list, tmp)
                return prelude_linked_object_get_object(tmp);

        return NULL;
}


/**
 * idmef_heartbeat_set_additional_data:
 * @ptr: pointer to a #idmef_heartbeat_t object.
 * @object: pointer to a #idmef_additional_data_t object.
 * @pos: Position in the list.
 *
 * Add @object to position @pos of @ptr list of #idmef_additional_data_t object.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 */
void idmef_heartbeat_set_additional_data(idmef_heartbeat_t *ptr, idmef_additional_data_t *object, int pos)
{
        prelude_return_if_fail(ptr);
        prelude_return_if_fail(object);

        if ( ! prelude_list_is_empty(&((prelude_linked_object_t *) object)->_list) )
                prelude_list_del_init(&((prelude_linked_object_t *) object)->_list);

        list_insert(&ptr->additional_data_list, &((prelude_linked_object_t *) object)->_list, pos);
}


/**
 * idmef_heartbeat_new_additional_data:
 * @ptr: pointer to a #idmef_heartbeat_t object.
 * @ret: pointer to an address where to store the created #idmef_additional_data_t object.
 * @pos: position in the list.
 *
 * Create a new #idmef_additional_data_t children of @ptr, and add it to position @pos of
 * @ptr list of #idmef_additional_data_t object. The created #idmef_additional_data_t object is
 * stored in @ret.
 *
 * If @pos is #IDMEF_LIST_APPEND, @object will be inserted at the tail of the list.
 * If @pos is #IDMEF_LIST_PREPEND, @object will be inserted at the head of the list.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_heartbeat_new_additional_data(idmef_heartbeat_t *ptr, idmef_additional_data_t **ret, int pos)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        retval = idmef_additional_data_new(ret);
        if ( retval < 0 )
                return retval;

        list_insert(&ptr->additional_data_list, &((prelude_linked_object_t *)(*ret))->_list, pos);

        return 0;
}


/**
 * idmef_heartbeat_copy:
 * @src: Source of the copy.
 * @dst: Where to copy the object.
 *
 * Copy a new #idmef_heartbeat_t object from @src to @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_heartbeat_copy(const idmef_heartbeat_t *src, idmef_heartbeat_t *dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));
        prelude_return_val_if_fail(dst, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = 0;

        if ( dst->messageid ) {
                prelude_string_destroy(dst->messageid);
                dst->messageid = NULL;
        }

        if ( src->messageid ) {
                ret = prelude_string_clone(src->messageid, &dst->messageid);
                if ( ret < 0 )
                        return ret;
        }

        {
                prelude_list_t *n, *tmp;
                idmef_analyzer_t *entry, *new;

                prelude_list_for_each_safe(&dst->analyzer_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        idmef_analyzer_destroy(entry);
                }

                prelude_list_for_each_safe(&src->analyzer_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        idmef_analyzer_clone(entry, &new);
                        prelude_list_add_tail(&dst->analyzer_list, &((prelude_linked_object_t *) new)->_list);
                }
        }

        if ( src->create_time ) {
                ret = idmef_time_copy(src->create_time, dst->create_time);
                if ( ret < 0 )
                        return ret;
        }

        if ( dst->analyzer_time ) {
                idmef_time_destroy(dst->analyzer_time);
                dst->analyzer_time = NULL;
        }

        if ( src->analyzer_time ) {
                ret = idmef_time_clone(src->analyzer_time, &dst->analyzer_time);
                if ( ret < 0 )
                        return ret;
        }

        dst->heartbeat_interval_is_set = src->heartbeat_interval_is_set;

        dst->heartbeat_interval = src->heartbeat_interval;

        {
                prelude_list_t *n, *tmp;
                idmef_additional_data_t *entry, *new;

                prelude_list_for_each_safe(&dst->additional_data_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        idmef_additional_data_destroy(entry);
                }

                prelude_list_for_each_safe(&src->additional_data_list, tmp, n) {
                        entry = prelude_linked_object_get_object(tmp);
                        idmef_additional_data_clone(entry, &new);
                        prelude_list_add_tail(&dst->additional_data_list, &((prelude_linked_object_t *) new)->_list);
                }
        }

        return 0;
}

/**
 * idmef_heartbeat_clone:
 * @src: Object to be cloned.
 * @dst: Address where to store the pointer to the cloned object.
 *
 * Create a copy of @src, and store it in @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_heartbeat_clone(idmef_heartbeat_t *src, idmef_heartbeat_t **dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = idmef_heartbeat_new(dst);
        if ( ret < 0 )
                return ret;

        return idmef_heartbeat_copy(src, *dst);
}

/**
 * idmef_heartbeat_compare:
 * @obj1: Object to compare with @obj2.
 * @obj2: Object to compare with @obj1.
 *
 * Compare @obj1 with @obj2.
 *
 * Returns: 0 on match, a negative value on comparison failure.
 */
int idmef_heartbeat_compare(const idmef_heartbeat_t *obj1, const idmef_heartbeat_t *obj2)
{
        int ret = 0;

        if ( obj1 == NULL && obj2 == NULL )
                return 0;

        else if ( obj1 == NULL || obj2 == NULL )
                return -1;

        ret = prelude_string_compare(obj1->messageid, obj2->messageid);
        if ( ret != 0 )
                return ret;

        {
                prelude_list_t *tmp1, *tmp2;
                idmef_analyzer_t *entry1, *entry2;

                tmp1 = tmp2 = NULL;
                do {
                        entry1 = entry2 = NULL;

                        prelude_list_for_each_continue(&obj1->analyzer_list, tmp1) {
                                entry1 = prelude_linked_object_get_object(tmp1);
                                break;
                        }

                        prelude_list_for_each_continue(&obj2->analyzer_list, tmp2) {
                                entry2 = prelude_linked_object_get_object(tmp2);
                                break;
                        }

                        ret = idmef_analyzer_compare(entry1, entry2);
                        if ( ret != 0 )
                                return ret;

                } while ( entry1 && entry2 );
        }

        ret = idmef_time_compare(obj1->create_time, obj2->create_time);
        if ( ret != 0 )
                return ret;

        ret = idmef_time_compare(obj1->analyzer_time, obj2->analyzer_time);
        if ( ret != 0 )
                return ret;

        if ( obj1->heartbeat_interval_is_set != obj2->heartbeat_interval_is_set )
                return -1;

        if ( obj1->heartbeat_interval_is_set && obj1->heartbeat_interval != obj2->heartbeat_interval )
                return -1;

        {
                prelude_list_t *tmp1, *tmp2;
                idmef_additional_data_t *entry1, *entry2;

                tmp1 = tmp2 = NULL;
                do {
                        entry1 = entry2 = NULL;

                        prelude_list_for_each_continue(&obj1->additional_data_list, tmp1) {
                                entry1 = prelude_linked_object_get_object(tmp1);
                                break;
                        }

                        prelude_list_for_each_continue(&obj2->additional_data_list, tmp2) {
                                entry2 = prelude_linked_object_get_object(tmp2);
                                break;
                        }

                        ret = idmef_additional_data_compare(entry1, entry2);
                        if ( ret != 0 )
                                return ret;

                } while ( entry1 && entry2 );
        }

        return ret;
}

/**
 * idmef_message_new:
 * @ret: Pointer where to store the created #idmef_message_t object.
 *
 * Create a new #idmef_message_t object.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_message_new(idmef_message_t **ret)
{
        *ret = calloc(1, sizeof(**ret));
        if ( ! *ret )
                return prelude_error_from_errno(errno);

        (*ret)->_idmef_object_id = IDMEF_CLASS_ID_MESSAGE;

        (*ret)->refcount = 1;

        {
                int retval = prelude_string_new(&(*ret)->version);

                if ( retval < 0 ) {
                        idmef_message_destroy(*ret);
                        *ret = NULL;
                        return retval;
                }
        }

        return 0;

}

/**
 * idmef_message_ref:
 * @message: pointer to a #idmef_message_t object.
 *
 * Increase @message reference count, so that it can be referenced
 * multiple time.
 *
 * Returns: a pointer to @message.
 */
idmef_message_t *idmef_message_ref(idmef_message_t *message)
{
        prelude_return_val_if_fail(message, NULL);
        message->refcount++;

        return message;
}

int _idmef_message_get_child(void *p, idmef_class_child_id_t child, void **childptr)
{
        idmef_message_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));
        *childptr = NULL;

        switch ( child ) {

                case 0:
                       return get_value_from_string((idmef_value_t **) childptr,  ptr->version, TRUE);
                case 1:
                        *childptr = ( ptr->type == IDMEF_MESSAGE_TYPE_ALERT ) ? ptr->message.alert : NULL;
                        return 0;

                case 2:
                        *childptr = ( ptr->type == IDMEF_MESSAGE_TYPE_HEARTBEAT ) ? ptr->message.heartbeat : NULL;
                        return 0;

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_message_new_child(void *p, idmef_class_child_id_t child, int n, void **ret)
{
        idmef_message_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        return idmef_message_new_version(ptr, (prelude_string_t **) ret);

                case 1:
                        return idmef_message_new_alert(ptr, (idmef_alert_t **) ret);

                case 2:
                        return idmef_message_new_heartbeat(ptr, (idmef_heartbeat_t **) ret);

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

int _idmef_message_destroy_child(void *p, idmef_class_child_id_t child, int n)
{
        idmef_message_t *ptr = p;

        prelude_return_val_if_fail(p, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( child ) {

                case 0:
                        if ( ptr->version ) {
                                prelude_string_destroy(ptr->version);
                                ptr->version = NULL;
                        }

                        return 0;

                case 1:
                        if (  ptr->type != IDMEF_MESSAGE_TYPE_ALERT )
                                return 0;

                        idmef_alert_destroy(ptr->message.alert);
                        ptr->message.alert = NULL;
                        ptr->type = 0;

                        return 0;

                case 2:
                        if (  ptr->type != IDMEF_MESSAGE_TYPE_HEARTBEAT )
                                return 0;

                        idmef_heartbeat_destroy(ptr->message.heartbeat);
                        ptr->message.heartbeat = NULL;
                        ptr->type = 0;

                        return 0;

                default:
                        return prelude_error(PRELUDE_ERROR_IDMEF_CLASS_UNKNOWN_CHILD);
        }
}

static void idmef_message_destroy_internal(idmef_message_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( ptr->version ) {
                prelude_string_destroy(ptr->version);
                ptr->version = NULL;
        }

        switch ( ptr->type ) {

                case IDMEF_MESSAGE_TYPE_ALERT:
                        idmef_alert_destroy(ptr->message.alert);
                        ptr->message.alert = NULL;
                        break;

                case IDMEF_MESSAGE_TYPE_HEARTBEAT:
                        idmef_heartbeat_destroy(ptr->message.heartbeat);
                        ptr->message.heartbeat = NULL;
                        break;

                default:
                        break;
        }


        /* free() should be done by the caller */
}

/**
 * idmef_message_get_version:
 * @ptr: pointer to a #idmef_message_t object.
 *
 * Get version children of the #idmef_message_t object.
 *
 * Returns: a pointer to a prelude_string_t object, or NULL if the children object is not set.
 */
prelude_string_t *idmef_message_get_version(idmef_message_t *ptr)
{
        prelude_return_val_if_fail(ptr, 0); /* FIXME */

        return ptr->version;
}

/**
 * idmef_message_set_version:
 * @ptr: pointer to a #idmef_message_t object.
 * @version: pointer to a #prelude_string_t object.
 *
 * Set @version object as a children of @ptr.
 * if @ptr already contain an @version object, then it is destroyed,
 * and updated to point to the provided @version object.
 */

void idmef_message_set_version(idmef_message_t *ptr, prelude_string_t *version)
{
        prelude_return_if_fail(ptr);

        if ( ptr->version )
                prelude_string_destroy(ptr->version);

        ptr->version = version;
}

/**
 * idmef_message_new_version:
 * @ptr: pointer to a #idmef_message_t object.
 * @ret: pointer to an address where to store the created #prelude_string_t object.
 *
 * Create a new version object, children of #idmef_message_t.
 * If @ptr already contain a #prelude_string_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_message_new_version(idmef_message_t *ptr, prelude_string_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        if ( ! ptr->version ) {
                retval = prelude_string_new(&ptr->version);
                if ( retval < 0 )
                        return retval;
        }

        *ret = ptr->version;
        return 0;
}

/**
 * idmef_message_get_type:
 * @ptr: pointer to a #idmef_message_t object.
 *
 * Access the type children of @ptr.
 *
 * Returns: a pointer to the #idmef_message_type_t children, or NULL if it is not set.
 */
idmef_message_type_t idmef_message_get_type(idmef_message_t *ptr)
{
        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));
        return ptr->type;
}

/**
 * idmef_message_get_alert:
 * @ptr: pointer to a #idmef_message_t object.
 *
 * Access the alert children of @ptr.
 *
 * Returns: a pointer to the #idmef_alert_t children, or NULL if it is not set.
 */
idmef_alert_t *idmef_message_get_alert(idmef_message_t *ptr)
{
        prelude_return_val_if_fail(ptr, NULL);
        return (ptr->type == IDMEF_MESSAGE_TYPE_ALERT) ? ptr->message.alert : NULL;
}

/**
 * idmef_message_set_alert:
 * @ptr: pointer to a #idmef_message_t object.
 * @alert: pointer to a #idmef_alert_t object.
 *
 * Set @alert object as a children of @ptr.
 * if @ptr already contain a @alert object, then it is destroyed,
 * and updated to point to the provided @alert object.
 */
void idmef_message_set_alert(idmef_message_t *ptr, idmef_alert_t *alert)
{
        prelude_return_if_fail(ptr);

        switch ( ptr->type ) {

                case IDMEF_MESSAGE_TYPE_ALERT:
                        idmef_alert_destroy(ptr->message.alert);
                        break;

                case IDMEF_MESSAGE_TYPE_HEARTBEAT:
                        idmef_heartbeat_destroy(ptr->message.heartbeat);
                        break;

                default:
                        break;
        }

        ptr->message.alert = alert;
        ptr->type = (alert) ? IDMEF_MESSAGE_TYPE_ALERT : 0;
}

/**
 * idmef_message_new_alert:
 * @ptr: pointer to a #idmef_message_t object.
 * @ret: pointer where to store the created #idmef_alert_t object.
 *
 * Create a new idmef_alert_t object, children of #idmef_message_t.
 * If @ptr already contain a #idmef_alert_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_message_new_alert(idmef_message_t *ptr, idmef_alert_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( ptr->type ) {

                case IDMEF_MESSAGE_TYPE_ALERT:
                        *ret = ptr->message.alert;
                        return 0;

                case IDMEF_MESSAGE_TYPE_HEARTBEAT:
                        idmef_heartbeat_destroy(ptr->message.heartbeat);
                        break;

                default:
                        break;
        }

        retval = idmef_alert_new(ret);
        if ( retval < 0 )
                return retval;

        ptr->type = IDMEF_MESSAGE_TYPE_ALERT;
        ptr->message.alert = *ret;

        return 0;
}

/**
 * idmef_message_get_heartbeat:
 * @ptr: pointer to a #idmef_message_t object.
 *
 * Access the heartbeat children of @ptr.
 *
 * Returns: a pointer to the #idmef_heartbeat_t children, or NULL if it is not set.
 */
idmef_heartbeat_t *idmef_message_get_heartbeat(idmef_message_t *ptr)
{
        prelude_return_val_if_fail(ptr, NULL);
        return (ptr->type == IDMEF_MESSAGE_TYPE_HEARTBEAT) ? ptr->message.heartbeat : NULL;
}

/**
 * idmef_message_set_heartbeat:
 * @ptr: pointer to a #idmef_message_t object.
 * @heartbeat: pointer to a #idmef_heartbeat_t object.
 *
 * Set @heartbeat object as a children of @ptr.
 * if @ptr already contain a @heartbeat object, then it is destroyed,
 * and updated to point to the provided @heartbeat object.
 */
void idmef_message_set_heartbeat(idmef_message_t *ptr, idmef_heartbeat_t *heartbeat)
{
        prelude_return_if_fail(ptr);

        switch ( ptr->type ) {

                case IDMEF_MESSAGE_TYPE_ALERT:
                        idmef_alert_destroy(ptr->message.alert);
                        break;

                case IDMEF_MESSAGE_TYPE_HEARTBEAT:
                        idmef_heartbeat_destroy(ptr->message.heartbeat);
                        break;

                default:
                        break;
        }

        ptr->message.heartbeat = heartbeat;
        ptr->type = (heartbeat) ? IDMEF_MESSAGE_TYPE_HEARTBEAT : 0;
}

/**
 * idmef_message_new_heartbeat:
 * @ptr: pointer to a #idmef_message_t object.
 * @ret: pointer where to store the created #idmef_heartbeat_t object.
 *
 * Create a new idmef_heartbeat_t object, children of #idmef_message_t.
 * If @ptr already contain a #idmef_heartbeat_t object, then it is destroyed.
 *
 * Returns: 0 on success, or a negative value if an error occured.
 */
int idmef_message_new_heartbeat(idmef_message_t *ptr, idmef_heartbeat_t **ret)
{
        int retval;

        prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));

        switch ( ptr->type ) {

                case IDMEF_MESSAGE_TYPE_ALERT:
                        idmef_alert_destroy(ptr->message.alert);
                        break;

                case IDMEF_MESSAGE_TYPE_HEARTBEAT:
                        *ret = ptr->message.heartbeat;
                        return 0;

                default:
                        break;
        }

        retval = idmef_heartbeat_new(ret);
        if ( retval < 0 )
                return retval;

        ptr->type = IDMEF_MESSAGE_TYPE_HEARTBEAT;
        ptr->message.heartbeat = *ret;

        return 0;
}

/**
 * idmef_message_copy:
 * @src: Source of the copy.
 * @dst: Where to copy the object.
 *
 * Copy a new #idmef_message_t object from @src to @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_message_copy(const idmef_message_t *src, idmef_message_t *dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));
        prelude_return_val_if_fail(dst, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = 0;

        if ( src->version ) {
                ret = prelude_string_copy(src->version, dst->version);
                if ( ret < 0 )
                        return ret;
        }

        switch ( dst->type ) {

                case IDMEF_MESSAGE_TYPE_ALERT:
                        idmef_alert_destroy(dst->message.alert);
                        break;

                case IDMEF_MESSAGE_TYPE_HEARTBEAT:
                        idmef_heartbeat_destroy(dst->message.heartbeat);
                        break;

                default:
                        break;
        }

        switch ( src->type ) {

                case IDMEF_MESSAGE_TYPE_ALERT:
                        ret = idmef_alert_clone(src->message.alert, &dst->message.alert);
                        break;

                case IDMEF_MESSAGE_TYPE_HEARTBEAT:
                        ret = idmef_heartbeat_clone(src->message.heartbeat, &dst->message.heartbeat);
                        break;

                default:
                        break;
        }

        if ( ret < 0 )
               return ret;

        dst->type = src->type;

        return 0;
}

/**
 * idmef_message_clone:
 * @src: Object to be cloned.
 * @dst: Address where to store the pointer to the cloned object.
 *
 * Create a copy of @src, and store it in @dst.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
int idmef_message_clone(idmef_message_t *src, idmef_message_t **dst)
{
        int ret;

        prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));

        ret = idmef_message_new(dst);
        if ( ret < 0 )
                return ret;

        return idmef_message_copy(src, *dst);
}

/**
 * idmef_message_compare:
 * @obj1: Object to compare with @obj2.
 * @obj2: Object to compare with @obj1.
 *
 * Compare @obj1 with @obj2.
 *
 * Returns: 0 on match, a negative value on comparison failure.
 */
int idmef_message_compare(const idmef_message_t *obj1, const idmef_message_t *obj2)
{
        int ret = 0;

        if ( obj1 == NULL && obj2 == NULL )
                return 0;

        else if ( obj1 == NULL || obj2 == NULL )
                return -1;

        ret = prelude_string_compare(obj1->version, obj2->version);
        if ( ret != 0 )
                return ret;

        if ( obj1->type != obj2->type )
                return -1;

        switch ( obj1->type ) {

                case IDMEF_MESSAGE_TYPE_ALERT:
                        ret = idmef_alert_compare(obj1->message.alert, obj2->message.alert);
                        break;

                case IDMEF_MESSAGE_TYPE_HEARTBEAT:
                        ret = idmef_heartbeat_compare(obj1->message.heartbeat, obj2->message.heartbeat);
                        break;

                default:
                        break;
        }

        return ret;
}


int _idmef_additional_data_type_is_set(idmef_additional_data_t *ad)
{
        return ad->_type_is_set;
}


void idmef_message_set_pmsg(idmef_message_t *message, prelude_msg_t *msg)
{
        prelude_return_if_fail(message);
        message->pmsg = msg;
}


prelude_msg_t *idmef_message_get_pmsg(idmef_message_t *message)
{
        prelude_return_val_if_fail(message, NULL);
        return message->pmsg;
}


/**
 * idmef_message_destroy:
 * @ptr: pointer to a #idmef_message_t object.
 *
 * Destroy @ptr and all of it's children.
 * The objects are only destroyed if their reference count reach zero.
 */
void idmef_message_destroy(idmef_message_t *ptr)
{
        prelude_return_if_fail(ptr);

        if ( --ptr->refcount )
                return;

        idmef_message_destroy_internal(ptr);

        if ( ptr->pmsg )
                prelude_msg_destroy(ptr->pmsg);

        free(ptr);
}
