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

struct rp_binding_commons_t
{
    rp_algorithmsuite_t *algorithmsuite;
    axis2_bool_t include_timestamp;
    rp_layout_t *layout;
    rp_supporting_tokens_t *signed_supporting_tokens;
    rp_supporting_tokens_t *signed_endorsing_supporting_tokens;
    rp_supporting_tokens_t *endorsing_supporting_tokens;
    rp_supporting_tokens_t *supporting_tokens;
};

AXIS2_EXTERN rp_binding_commons_t *AXIS2_CALL
rp_binding_commons_create(
    const axutil_env_t *env)
{
    rp_binding_commons_t *binding_commons = NULL;

    AXIS2_ENV_CHECK(env, NULL);

    binding_commons = (rp_binding_commons_t *)AXIS2_MALLOC(env->allocator,
        sizeof(rp_binding_commons_t));

    if(binding_commons == 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;
    }
    binding_commons->algorithmsuite = NULL;
    binding_commons->include_timestamp = AXIS2_FALSE;
    binding_commons->layout = NULL;
    binding_commons->signed_supporting_tokens = NULL;
    binding_commons->signed_endorsing_supporting_tokens = NULL;
    binding_commons->endorsing_supporting_tokens = NULL;
    binding_commons->supporting_tokens = NULL;

    return binding_commons;

}

AXIS2_EXTERN void AXIS2_CALL
rp_binding_commons_free(
    rp_binding_commons_t *binding_commons,
    const axutil_env_t *env)
{
    if(binding_commons)
    {
        if(binding_commons->algorithmsuite)
        {
            rp_algorithmsuite_free(binding_commons->algorithmsuite, env);
            binding_commons->algorithmsuite = NULL;
        }
        if(binding_commons->layout)
        {
            rp_layout_free(binding_commons->layout, env);
            binding_commons->layout = NULL;
        }
        if(binding_commons->signed_supporting_tokens)
        {
            rp_supporting_tokens_free(binding_commons->signed_supporting_tokens, env);
            binding_commons->signed_supporting_tokens = NULL;
        }
        if(binding_commons->signed_endorsing_supporting_tokens)
        {
            rp_supporting_tokens_free(binding_commons-> signed_endorsing_supporting_tokens, env);
            binding_commons->signed_endorsing_supporting_tokens = NULL;
        }
        if(binding_commons->endorsing_supporting_tokens)
        {
            rp_supporting_tokens_free(binding_commons-> endorsing_supporting_tokens, env);
            binding_commons->endorsing_supporting_tokens = NULL;
        }
        if(binding_commons->supporting_tokens)
        {
            rp_supporting_tokens_free(binding_commons->supporting_tokens, env);
            binding_commons->supporting_tokens = NULL;
        }
        AXIS2_FREE(env->allocator, binding_commons);
        binding_commons = NULL;

    }
    return;
}

/* Implementations */

AXIS2_EXTERN axis2_bool_t AXIS2_CALL
rp_binding_commons_get_include_timestamp(
    rp_binding_commons_t *binding_commons,
    const axutil_env_t *env)
{
    return binding_commons->include_timestamp;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
rp_binding_commons_set_include_timestamp(
    rp_binding_commons_t *binding_commons,
    const axutil_env_t *env,
    axis2_bool_t include_timestamp)
{
    AXIS2_ENV_CHECK(env, AXIS2_FAILURE);
    AXIS2_PARAM_CHECK(env->error, include_timestamp, AXIS2_FAILURE);

    binding_commons->include_timestamp = include_timestamp;

    return AXIS2_SUCCESS;

}

AXIS2_EXTERN rp_algorithmsuite_t *AXIS2_CALL
rp_binding_commons_get_algorithmsuite(
    rp_binding_commons_t *binding_commons,
    const axutil_env_t *env)
{
    return binding_commons->algorithmsuite;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
rp_binding_commons_set_algorithmsuite(
    rp_binding_commons_t *binding_commons,
    const axutil_env_t *env,
    rp_algorithmsuite_t *algorithmsuite)
{
    AXIS2_PARAM_CHECK(env->error, algorithmsuite, AXIS2_FAILURE);

    rp_algorithmsuite_increment_ref(algorithmsuite, env);
    binding_commons->algorithmsuite = algorithmsuite;
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN rp_layout_t *AXIS2_CALL
rp_binding_commons_get_layout(
    rp_binding_commons_t *binding_commons,
    const axutil_env_t *env)
{
    return binding_commons->layout;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
rp_binding_commons_set_layout(
    rp_binding_commons_t *binding_commons,
    const axutil_env_t *env,
    rp_layout_t *layout)
{
    AXIS2_PARAM_CHECK(env->error, layout, AXIS2_FAILURE);
    rp_layout_increment_ref(layout, env);
    binding_commons->layout = layout;
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN rp_supporting_tokens_t *AXIS2_CALL
rp_binding_commons_get_signed_supporting_tokens(
    rp_binding_commons_t *binding_commons,
    const axutil_env_t *env)
{
    return binding_commons->signed_supporting_tokens;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
rp_binding_commons_set_signed_supporting_tokens(
    rp_binding_commons_t *binding_commons,
    const axutil_env_t *env,
    rp_supporting_tokens_t *signed_supporting_tokens)
{
    AXIS2_PARAM_CHECK(env->error, signed_supporting_tokens, AXIS2_FAILURE);
    binding_commons->signed_supporting_tokens = signed_supporting_tokens;
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN rp_supporting_tokens_t *AXIS2_CALL
rp_binding_commons_get_signed_endorsing_supporting_tokens(
    rp_binding_commons_t *binding_commons,
    const axutil_env_t *env)
{
    return binding_commons->signed_endorsing_supporting_tokens;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
rp_binding_commons_set_signed_endorsing_supporting_tokens(
    rp_binding_commons_t *binding_commons,
    const axutil_env_t *env,
    rp_supporting_tokens_t *signed_endorsing_supporting_tokens)
{
    AXIS2_PARAM_CHECK(env->error, signed_endorsing_supporting_tokens, AXIS2_FAILURE);

    binding_commons->signed_endorsing_supporting_tokens = signed_endorsing_supporting_tokens;
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN rp_supporting_tokens_t *AXIS2_CALL
rp_binding_commons_get_endorsing_supporting_tokens(
    rp_binding_commons_t *binding_commons,
    const axutil_env_t *env)
{
    return binding_commons->endorsing_supporting_tokens;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
rp_binding_commons_set_endorsing_supporting_tokens(
    rp_binding_commons_t *binding_commons,
    const axutil_env_t *env,
    rp_supporting_tokens_t *endorsing_supporting_tokens)
{
    AXIS2_PARAM_CHECK(env->error, endorsing_supporting_tokens, AXIS2_FAILURE);
    binding_commons->endorsing_supporting_tokens = endorsing_supporting_tokens;
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN rp_supporting_tokens_t *AXIS2_CALL
rp_binding_commons_get_supporting_tokens(
    rp_binding_commons_t *binding_commons,
    const axutil_env_t *env)
{
    return binding_commons->supporting_tokens;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
rp_binding_commons_set_supporting_tokens(
    rp_binding_commons_t *binding_commons,
    const axutil_env_t *env,
    rp_supporting_tokens_t *supporting_tokens)
{
    AXIS2_PARAM_CHECK(env->error, supporting_tokens, AXIS2_FAILURE);
    binding_commons->supporting_tokens = supporting_tokens;
    return AXIS2_SUCCESS;
}
