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

struct rp_signed_encrypted_elements_t
{
    axis2_bool_t signedelements;
    axutil_array_list_t *xpath_expressions;
    axis2_char_t *xpath_version;
    int ref;

};

AXIS2_EXTERN rp_signed_encrypted_elements_t *AXIS2_CALL
rp_signed_encrypted_elements_create(
    const axutil_env_t * env)
{
    rp_signed_encrypted_elements_t *signed_encrypted_elements = NULL;

    AXIS2_ENV_CHECK(env, NULL);

    signed_encrypted_elements = (rp_signed_encrypted_elements_t *)AXIS2_MALLOC(env->allocator,
        sizeof(rp_signed_encrypted_elements_t));

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

    signed_encrypted_elements->xpath_expressions = axutil_array_list_create(env, 0);
    if(!(signed_encrypted_elements->xpath_expressions))
    {
        rp_signed_encrypted_elements_free(signed_encrypted_elements, env);
        AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
        return NULL;
    }

    signed_encrypted_elements->xpath_version = NULL;
    signed_encrypted_elements->ref = 0;

    return signed_encrypted_elements;

}

AXIS2_EXTERN void AXIS2_CALL
rp_signed_encrypted_elements_free(
    rp_signed_encrypted_elements_t * signed_encrypted_elements,
    const axutil_env_t * env)
{
    AXIS2_ENV_CHECK(env, AXIS2_FAILURE);

    if(signed_encrypted_elements)
    {
        if(--(signed_encrypted_elements->ref) > 0)
        {
            return;
        }

        if(signed_encrypted_elements->xpath_expressions)
        {
            int i = 0;
            for(i = 0; i < axutil_array_list_size(signed_encrypted_elements-> xpath_expressions,
                env); i++)
            {
                axis2_char_t *expression = NULL;
                expression = (axis2_char_t *)axutil_array_list_get(
                    signed_encrypted_elements-> xpath_expressions, env, i);
                if(expression)
                    AXIS2_FREE(env->allocator, expression);

                expression = NULL;
            }
            axutil_array_list_free(signed_encrypted_elements->xpath_expressions, env);
            signed_encrypted_elements->xpath_expressions = NULL;

        }
        AXIS2_FREE(env->allocator, signed_encrypted_elements);
        signed_encrypted_elements = NULL;
    }
    return;
}

/* Implementations */

AXIS2_EXTERN axis2_bool_t AXIS2_CALL
rp_signed_encrypted_elements_get_signedelements(
    rp_signed_encrypted_elements_t * signed_encrypted_elements,
    const axutil_env_t * env)
{
    AXIS2_ENV_CHECK(env, AXIS2_FAILURE);

    return signed_encrypted_elements->signedelements;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
rp_signed_encrypted_elements_set_signedelements(
    rp_signed_encrypted_elements_t * signed_encrypted_elements,
    const axutil_env_t * env,
    axis2_bool_t signedelements)
{
    AXIS2_ENV_CHECK(env, AXIS2_FAILURE);
    AXIS2_PARAM_CHECK(env->error, signedelements, AXIS2_FAILURE);

    signed_encrypted_elements->signedelements = signedelements;
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN axutil_array_list_t *AXIS2_CALL
rp_signed_encrypted_elements_get_xpath_expressions(
    rp_signed_encrypted_elements_t * signed_encrypted_elements,
    const axutil_env_t * env)
{
    AXIS2_ENV_CHECK(env, AXIS2_FAILURE);

    return signed_encrypted_elements->xpath_expressions;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
rp_signed_encrypted_elements_add_expression(
    rp_signed_encrypted_elements_t * signed_encrypted_elements,
    const axutil_env_t * env,
    axis2_char_t * expression)
{
    AXIS2_ENV_CHECK(env, AXIS2_FAILURE);
    AXIS2_PARAM_CHECK(env->error, expression, AXIS2_FAILURE);

    axutil_array_list_add(signed_encrypted_elements->xpath_expressions, env, expression);
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN axis2_char_t *AXIS2_CALL
rp_signed_encrypted_elements_get_xpath_version(
    rp_signed_encrypted_elements_t * signed_encrypted_elements,
    const axutil_env_t * env)
{
    AXIS2_ENV_CHECK(env, AXIS2_FAILURE);

    return signed_encrypted_elements->xpath_version;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
rp_signed_encrypted_elements_set_xpath_version(
    rp_signed_encrypted_elements_t * signed_encrypted_elements,
    const axutil_env_t * env,
    axis2_char_t * xpath_version)
{

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

    signed_encrypted_elements->xpath_version = xpath_version;
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
rp_signed_encrypted_elements_increment_ref(
    rp_signed_encrypted_elements_t * signed_encrypted_elements,
    const axutil_env_t * env)
{
    AXIS2_ENV_CHECK(env, AXIS2_FAILURE);
    signed_encrypted_elements->ref++;
    return AXIS2_SUCCESS;
}
