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

struct neethi_exactlyone_t
{
    axutil_array_list_t *policy_components;
};

AXIS2_EXTERN neethi_exactlyone_t *AXIS2_CALL
neethi_exactlyone_create(
    const axutil_env_t *env)
{
    neethi_exactlyone_t *neethi_exactlyone = NULL;

    AXIS2_ENV_CHECK(env, NULL);

    neethi_exactlyone = (neethi_exactlyone_t *)AXIS2_MALLOC(env->allocator,
        sizeof(neethi_exactlyone_t));

    if(neethi_exactlyone == NULL)
    {
        AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory");
        return NULL;
    }
    neethi_exactlyone->policy_components = NULL;

    neethi_exactlyone->policy_components = axutil_array_list_create(env, 0);
    if(!(neethi_exactlyone->policy_components))
    {
        neethi_exactlyone_free(neethi_exactlyone, env);
        AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory");
        return NULL;
    }
    return neethi_exactlyone;
}

AXIS2_EXTERN void AXIS2_CALL
neethi_exactlyone_free(
    neethi_exactlyone_t *neethi_exactlyone,
    const axutil_env_t *env)
{
    if(neethi_exactlyone)
    {
        if(neethi_exactlyone->policy_components)
        {
            int i = 0;
            int size = 0;

            size = axutil_array_list_size(neethi_exactlyone->policy_components, env);

            for(i = 0; i < size; i++)
            {
                neethi_operator_t *operator = NULL;
                operator = (neethi_operator_t *)axutil_array_list_get(
                    neethi_exactlyone->policy_components, env, i);
                if(operator)
                {
                    neethi_operator_free(operator, env);
                    operator = NULL;
                }
            }
            axutil_array_list_free(neethi_exactlyone->policy_components, env);
            neethi_exactlyone->policy_components = NULL;
        }
        AXIS2_FREE(env->allocator, neethi_exactlyone);
        neethi_exactlyone = NULL;
    }
    return;
}

/* Implementations */

AXIS2_EXTERN axutil_array_list_t *AXIS2_CALL
neethi_exactlyone_get_policy_components(
    neethi_exactlyone_t *neethi_exactlyone,
    const axutil_env_t *env)
{
    return neethi_exactlyone->policy_components;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
neethi_exactlyone_add_policy_components(
    neethi_exactlyone_t *exactlyone,
    axutil_array_list_t *arraylist,
    const axutil_env_t *env)
{

    int size = axutil_array_list_size(arraylist, env);
    int i = 0;

    if(axutil_array_list_ensure_capacity(exactlyone->policy_components, env, size + 1)
        != AXIS2_SUCCESS)
    {
        return AXIS2_FAILURE;
    }

    for(i = 0; i < size; i++)
    {
        void *value = NULL;
        value = axutil_array_list_get(arraylist, env, i);
        neethi_operator_increment_ref((neethi_operator_t *)value, env);
        axutil_array_list_add(exactlyone->policy_components, env, value);
    }
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
neethi_exactlyone_add_operator(
    neethi_exactlyone_t *neethi_exactlyone,
    const axutil_env_t *env,
    neethi_operator_t *operator)
{
    neethi_operator_increment_ref(operator, env);
    axutil_array_list_add(neethi_exactlyone->policy_components, env, operator);
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN axis2_bool_t AXIS2_CALL
neethi_exactlyone_is_empty(
    neethi_exactlyone_t *exactlyone,
    const axutil_env_t *env)
{
    return axutil_array_list_is_empty(exactlyone->policy_components, env);
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
neethi_exactlyone_serialize(
    neethi_exactlyone_t *neethi_exactlyone,
    axiom_node_t *parent,
    const axutil_env_t *env)
{
    axiom_node_t *exactlyone_node = NULL;
    axiom_element_t *exactlyone_ele = NULL;
    axiom_namespace_t *policy_ns = NULL;
    axutil_array_list_t *components = NULL;

    policy_ns = axiom_namespace_create(env, NEETHI_NAMESPACE, NEETHI_PREFIX);
    exactlyone_ele = axiom_element_create(env, parent, NEETHI_EXACTLYONE, policy_ns,
        &exactlyone_node);
    if(!exactlyone_node)
    {
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
            "Cannot create 'ExactlyOne' node. Serialization of 'ExactlyOne' assertion failed");
        return AXIS2_FAILURE;
    }

    components = neethi_exactlyone_get_policy_components(neethi_exactlyone, env);
    if(components)
    {
        axis2_status_t status = AXIS2_FAILURE;
        int i = 0;
        for(i = 0; i < axutil_array_list_size(components, env); i++)
        {
            neethi_operator_t *operator = NULL;
            operator = (neethi_operator_t *)axutil_array_list_get(components, env, i);
            if(operator)
            {
                status = neethi_operator_serialize(operator, env, exactlyone_node);
                if(status != AXIS2_SUCCESS)
                {
                    AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
                        "Neethi operator serialization failed. "
                            "Cannot serialize 'ExactlyOne' assertion");
                    return AXIS2_FAILURE;
                }
            }
        }
    }
    return AXIS2_SUCCESS;
}
