/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <axis2_relates_to.h>
#include <axutil_string.h>

struct axis2_relates_to
{

    /** value string  */
    axis2_char_t *value;

    /** relationship type string */
    axis2_char_t *relationship_type;
};

axis2_relates_to_t *AXIS2_CALL
axis2_relates_to_create(
    const axutil_env_t * env,
    const axis2_char_t * value,
    const axis2_char_t * relationship_type)
{
    axis2_relates_to_t *relates_to = NULL;

    AXIS2_ENV_CHECK(env, NULL);

    relates_to = AXIS2_MALLOC(env->allocator, sizeof(axis2_relates_to_t));
    if(!relates_to)
    {
        AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
        return NULL;
    }

    relates_to->value = NULL;
    relates_to->relationship_type = NULL;

    if(value)
    {
        relates_to->value = axutil_strdup(env, value);
        if(!(relates_to->value))
        {
            AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
            axis2_relates_to_free(relates_to, env);
            return NULL;
        }
    }

    if(relationship_type)
    {
        relates_to->relationship_type = axutil_strdup(env, relationship_type);
        if(!(relates_to->relationship_type))
        {
            AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
            axis2_relates_to_free(relates_to, env);
            return NULL;
        }
    }

    return relates_to;
}

const axis2_char_t *AXIS2_CALL
axis2_relates_to_get_value(
    const axis2_relates_to_t * relates_to,
    const axutil_env_t * env)
{
    return relates_to->value;
}

axis2_status_t AXIS2_CALL
axis2_relates_to_set_value(
    struct axis2_relates_to * relates_to,
    const axutil_env_t * env,
    const axis2_char_t * value)
{
    AXIS2_ENV_CHECK(env, AXIS2_FAILURE);

    if(relates_to->value)
    {
        AXIS2_FREE(env->allocator, relates_to->value);
    }

    if(value)
    {
        relates_to->value = (axis2_char_t *)axutil_strdup(env, value);
        if(!(relates_to->value))
        {
            AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
            return AXIS2_FAILURE;
        }
    }

    return AXIS2_SUCCESS;
}

const axis2_char_t *AXIS2_CALL
axis2_relates_to_get_relationship_type(
    const axis2_relates_to_t * relates_to,
    const axutil_env_t * env)
{
    return relates_to->relationship_type;
}

axis2_status_t AXIS2_CALL
axis2_relates_to_set_relationship_type(
    struct axis2_relates_to * relates_to,
    const axutil_env_t * env,
    const axis2_char_t * relationship_type)
{
    AXIS2_ENV_CHECK(env, AXIS2_FAILURE);

    if(relates_to->relationship_type)
    {
        AXIS2_FREE(env->allocator, relates_to->relationship_type);
    }

    if(relationship_type)
    {
        relates_to->relationship_type = (axis2_char_t *)axutil_strdup(env, relationship_type);
        if(!(relates_to->relationship_type))
        {
            AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
            return AXIS2_FAILURE;
        }
    }

    return AXIS2_SUCCESS;
}

void AXIS2_CALL
axis2_relates_to_free(
    struct axis2_relates_to *relates_to,
    const axutil_env_t * env)
{
    AXIS2_ENV_CHECK(env, void);

    if(relates_to->value)
    {
        AXIS2_FREE(env->allocator, relates_to->value);
    }

    if(relates_to->relationship_type)
    {
        AXIS2_FREE(env->allocator, relates_to->relationship_type);
    }

    AXIS2_FREE(env->allocator, relates_to);

    return;
}
