/*
 * 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 <axiom_soap_fault_role.h>
#include "_axiom_soap_fault.h"
#include <axiom_soap_builder.h>
#include <axiom_element.h>

struct axiom_soap_fault_role
{
    axiom_node_t *om_ele_node;
};

AXIS2_EXTERN axiom_soap_fault_role_t *AXIS2_CALL
axiom_soap_fault_role_create(
    const axutil_env_t * env)
{
    axiom_soap_fault_role_t *fault_role = NULL;

    fault_role = (axiom_soap_fault_role_t *)AXIS2_MALLOC(env->allocator,
        sizeof(axiom_soap_fault_role_t));

    if(!fault_role)
    {
        AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "No memory. Cannot create SOAP fault role");
        return NULL;
    }

    fault_role->om_ele_node = NULL;

    return fault_role;
}

AXIS2_EXTERN axiom_soap_fault_role_t *AXIS2_CALL
axiom_soap_fault_role_create_with_parent(
    const axutil_env_t * env,
    axiom_soap_fault_t * fault)
{
    axiom_soap_fault_role_t *fault_role = NULL;
    int soap_version = -1;

    axiom_element_t *this_ele = NULL;
    axiom_node_t *this_node = NULL;

    axiom_node_t *parent_node = NULL;
    axiom_element_t *parent_ele = NULL;

    axiom_namespace_t *parent_ns = NULL;

    AXIS2_PARAM_CHECK(env->error, fault, NULL);

    fault_role = axiom_soap_fault_role_create(env);
    if(!fault_role)
    {
        return NULL;
    }
    parent_node = axiom_soap_fault_get_base_node(fault, env);
    if(!parent_node)
    {
        axiom_soap_fault_role_free(fault_role, env);
        return NULL;
    }
    parent_ele = (axiom_element_t *)axiom_node_get_data_element(parent_node, env);

    if(!parent_ele)
    {
        axiom_soap_fault_role_free(fault_role, env);
        return NULL;
    }
    soap_version = axiom_soap_fault_get_soap_version(fault, env);
    if(soap_version == AXIOM_SOAP12)
    {
        parent_ns = axiom_element_get_namespace(parent_ele, env, parent_node);
    }
    this_ele = axiom_element_create(env, parent_node, AXIOM_SOAP12_SOAP_FAULT_ROLE_LOCAL_NAME,
        parent_ns, &this_node);

    if(!this_ele)
    {
        axiom_soap_fault_role_free(fault_role, env);
        return NULL;
    }

    fault_role->om_ele_node = this_node;

    axiom_soap_fault_set_role(fault, env, fault_role);

    return fault_role;
}

AXIS2_EXTERN void AXIS2_CALL
axiom_soap_fault_role_free(
    axiom_soap_fault_role_t * fault_role,
    const axutil_env_t * env)
{
    AXIS2_FREE(env->allocator, fault_role);
    return;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
axiom_soap_fault_role_set_role_value(
    axiom_soap_fault_role_t * fault_role,
    const axutil_env_t * env,
    axis2_char_t * uri)
{
    axiom_element_t *role_ele = NULL;

    AXIS2_PARAM_CHECK(env->error, uri, AXIS2_FAILURE);

    if(!fault_role->om_ele_node)
    {
        return AXIS2_FAILURE;
    }
    role_ele = (axiom_element_t *)axiom_node_get_data_element(fault_role->om_ele_node, env);

    if(role_ele)
    {
        return axiom_element_set_text(role_ele, env, uri, fault_role->om_ele_node);
    }
    return AXIS2_FAILURE;
}

AXIS2_EXTERN axis2_char_t *AXIS2_CALL axiom_soap_fault_role_get_role_value(
    axiom_soap_fault_role_t * fault_role,
    const axutil_env_t * env)
{
    axiom_element_t *role_ele = NULL;

    if (!fault_role->om_ele_node)
    {
        return NULL;
    }
    role_ele = (axiom_element_t *) axiom_node_get_data_element
    (fault_role->om_ele_node, env);

    if (role_ele)
    {
        return axiom_element_get_text(role_ele, env, fault_role->om_ele_node);
    }
    return NULL;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
axiom_soap_fault_role_set_base_node(
    axiom_soap_fault_role_t * fault_role,
    const axutil_env_t * env,
    axiom_node_t * node)
{
    AXIS2_PARAM_CHECK(env->error, node, AXIS2_FAILURE);

    if(axiom_node_get_node_type(node, env) != AXIOM_ELEMENT)
    {
        AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_INVALID_BASE_TYPE, AXIS2_FAILURE);
        return AXIS2_FAILURE;
    }
    fault_role->om_ele_node = node;
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN axiom_node_t *AXIS2_CALL axiom_soap_fault_role_get_base_node(
    axiom_soap_fault_role_t * fault_role,
    const axutil_env_t * env)
{
    return fault_role->om_ele_node;
}
