/*
 * 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_wsdl_extensible_attribute.h>

/**
 * @brief Wsdl extensible attribute struct impl
 *   Wsdl extensible attribute
 */
typedef struct axis2_wsdl_extensible_attribute_impl
{
    axis2_wsdl_extensible_attribute_t extensible_attribute;

    axis2_qname_t *key;
    axis2_qname_t *value;


}
axis2_wsdl_extensible_attribute_impl_t;

#define AXIS2_INTF_TO_IMPL(extensible_attribute) \
      ((axis2_wsdl_extensible_attribute_impl_t *)extensible_attribute)

/************************* Function prototypes ********************************/

axis2_status_t AXIS2_CALL
axis2_wsdl_extensible_attribute_free(
    axis2_wsdl_extensible_attribute_t *extensible_attribute,
    const axis2_env_t *env);

axis2_qname_t *AXIS2_CALL
axis2_wsdl_extensible_attribute_get_key(
    axis2_wsdl_extensible_attribute_t *extensible_attribute,
    const axis2_env_t *env);

axis2_status_t AXIS2_CALL
axis2_wsdl_extensible_attribute_set_key(
    axis2_wsdl_extensible_attribute_t *extensible_attribute,
    const axis2_env_t *env,
    axis2_qname_t *key);

axis2_qname_t *AXIS2_CALL
axis2_wsdl_extensible_attribute_get_value(
    axis2_wsdl_extensible_attribute_t *extensible_attribute,
    const axis2_env_t *env);

axis2_status_t AXIS2_CALL
axis2_wsdl_extensible_attribute_set_value(
    axis2_wsdl_extensible_attribute_t *extensible_attribute,
    const axis2_env_t *env,
    axis2_qname_t *value);

/************************** End of function prototypes ************************/

axis2_wsdl_extensible_attribute_t * AXIS2_CALL
axis2_wsdl_extensible_attribute_create(const axis2_env_t *env)
{
    axis2_wsdl_extensible_attribute_impl_t *extensible_attribute_impl = NULL;

    AXIS2_ENV_CHECK(env, NULL);

    extensible_attribute_impl = (axis2_wsdl_extensible_attribute_impl_t *)
            AXIS2_MALLOC(env->allocator, sizeof(axis2_wsdl_extensible_attribute_impl_t));


    if (NULL == extensible_attribute_impl)
    {
        AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
        return NULL;
    }

    extensible_attribute_impl->key = NULL;
    extensible_attribute_impl->value = NULL;
    extensible_attribute_impl->extensible_attribute.ops = NULL;

    extensible_attribute_impl->extensible_attribute.ops =
        AXIS2_MALLOC(env->allocator, sizeof(axis2_wsdl_extensible_attribute_ops_t));
    if (NULL == extensible_attribute_impl->extensible_attribute.ops)
    {
        axis2_wsdl_extensible_attribute_free(&(extensible_attribute_impl->
                extensible_attribute), env);
        AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
        return NULL;
    }

    extensible_attribute_impl->extensible_attribute.ops->free =
        axis2_wsdl_extensible_attribute_free;

    extensible_attribute_impl->extensible_attribute.ops->get_key =
        axis2_wsdl_extensible_attribute_get_key;
    extensible_attribute_impl->extensible_attribute.ops->set_key =
        axis2_wsdl_extensible_attribute_set_key;
    extensible_attribute_impl->extensible_attribute.ops->get_value =
        axis2_wsdl_extensible_attribute_get_value;
    extensible_attribute_impl->extensible_attribute.ops->set_value =
        axis2_wsdl_extensible_attribute_set_value;


    return &(extensible_attribute_impl->extensible_attribute);
}

/***************************Function implementation****************************/

axis2_status_t AXIS2_CALL
axis2_wsdl_extensible_attribute_free(
    axis2_wsdl_extensible_attribute_t *extensible_attribute,
    const axis2_env_t *env)
{
    AXIS2_ENV_CHECK(env, AXIS2_FAILURE);
    if (extensible_attribute->ops)
        AXIS2_FREE(env->allocator, extensible_attribute->ops);

    if (AXIS2_INTF_TO_IMPL(extensible_attribute)->key)
    {
        AXIS2_QNAME_FREE(AXIS2_INTF_TO_IMPL(extensible_attribute)->
                key, env);
        AXIS2_INTF_TO_IMPL(extensible_attribute)->key = NULL;
    }

    if (AXIS2_INTF_TO_IMPL(extensible_attribute)->value)
    {
        AXIS2_QNAME_FREE(AXIS2_INTF_TO_IMPL(extensible_attribute)->
                value, env);
        AXIS2_INTF_TO_IMPL(extensible_attribute)->value = NULL;
    }

    AXIS2_FREE(env->allocator, AXIS2_INTF_TO_IMPL(extensible_attribute));

    return AXIS2_SUCCESS;
}

axis2_qname_t *AXIS2_CALL
axis2_wsdl_extensible_attribute_get_key(
    axis2_wsdl_extensible_attribute_t *extensible_attribute,
    const axis2_env_t *env)
{
    AXIS2_ENV_CHECK(env, NULL);
    return AXIS2_INTF_TO_IMPL(extensible_attribute)->key;
}

axis2_status_t AXIS2_CALL
axis2_wsdl_extensible_attribute_set_key(
    axis2_wsdl_extensible_attribute_t *extensible_attribute,
    const axis2_env_t *env,
    axis2_qname_t *key)
{
    axis2_wsdl_extensible_attribute_impl_t *extensible_attribute_impl =
        AXIS2_INTF_TO_IMPL(extensible_attribute);

    AXIS2_ENV_CHECK(env, AXIS2_FAILURE);
    AXIS2_PARAM_CHECK(env->error, key, AXIS2_FAILURE);

    if (extensible_attribute_impl->key)
    {
        AXIS2_QNAME_FREE(extensible_attribute_impl->key, env);
        extensible_attribute_impl->key = NULL;
    }

    extensible_attribute_impl->key = AXIS2_QNAME_CLONE(key, env);
    if (!extensible_attribute_impl->key)
    {
        AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
        return AXIS2_FAILURE;
    }
    return AXIS2_SUCCESS;
}

axis2_qname_t *AXIS2_CALL
axis2_wsdl_extensible_attribute_get_value(
    axis2_wsdl_extensible_attribute_t *extensible_attribute,
    const axis2_env_t *env)
{
    AXIS2_ENV_CHECK(env, NULL);
    return AXIS2_INTF_TO_IMPL(extensible_attribute)->value;
}

axis2_status_t AXIS2_CALL
axis2_wsdl_extensible_attribute_set_value(
    axis2_wsdl_extensible_attribute_t *extensible_attribute,
    const axis2_env_t *env,
    axis2_qname_t *value)
{
    axis2_wsdl_extensible_attribute_impl_t *extensible_attribute_impl =
        AXIS2_INTF_TO_IMPL(extensible_attribute);

    AXIS2_ENV_CHECK(env, AXIS2_FAILURE);
    AXIS2_PARAM_CHECK(env->error, value, AXIS2_FAILURE);

    if (extensible_attribute_impl->value)
    {
        AXIS2_QNAME_FREE(extensible_attribute_impl->value, env);
        extensible_attribute_impl->value = NULL;
    }

    extensible_attribute_impl->value = AXIS2_QNAME_CLONE(value, env);
    if (!extensible_attribute_impl->value)
    {
        AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
        return AXIS2_FAILURE;
    }
    return AXIS2_SUCCESS;
}
