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

struct rp_asymmetric_binding_t
{
    rp_symmetric_asymmetric_binding_commons_t *symmetric_asymmetric_binding_commons;
    rp_property_t *initiator_token;
    rp_property_t *recipient_token;
    int ref;
};

AXIS2_EXTERN rp_asymmetric_binding_t *AXIS2_CALL
rp_asymmetric_binding_create(
    const axutil_env_t *env)
{
    rp_asymmetric_binding_t *asymmetric_binding = NULL;

    AXIS2_ENV_CHECK(env, NULL);

    asymmetric_binding = (rp_asymmetric_binding_t *)AXIS2_MALLOC(env->allocator,
        sizeof(rp_asymmetric_binding_t));

    if(asymmetric_binding == 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;
    }
    asymmetric_binding->symmetric_asymmetric_binding_commons = NULL;
    asymmetric_binding->initiator_token = NULL;
    asymmetric_binding->recipient_token = NULL;
    asymmetric_binding->ref = 0;

    return asymmetric_binding;

}

AXIS2_EXTERN void AXIS2_CALL
rp_asymmetric_binding_free(
    rp_asymmetric_binding_t *asymmetric_binding,
    const axutil_env_t *env)
{
    if(asymmetric_binding)
    {

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

        if(asymmetric_binding->symmetric_asymmetric_binding_commons)
        {
            rp_symmetric_asymmetric_binding_commons_free(
                asymmetric_binding-> symmetric_asymmetric_binding_commons, env);
            asymmetric_binding->symmetric_asymmetric_binding_commons = NULL;
        }
        if(asymmetric_binding->initiator_token)
        {
            rp_property_free(asymmetric_binding->initiator_token, env);
            asymmetric_binding->initiator_token = NULL;
        }
        if(asymmetric_binding->recipient_token)
        {
            rp_property_free(asymmetric_binding->recipient_token, env);
            asymmetric_binding->recipient_token = NULL;
        }
        AXIS2_FREE(env->allocator, asymmetric_binding);
    }

    return;
}

/* Implementations */

AXIS2_EXTERN rp_symmetric_asymmetric_binding_commons_t *AXIS2_CALL
rp_asymmetric_binding_get_symmetric_asymmetric_binding_commons(
    rp_asymmetric_binding_t *asymmetric_binding,
    const axutil_env_t *env)
{
    return asymmetric_binding->symmetric_asymmetric_binding_commons;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
rp_asymmetric_binding_set_symmetric_asymmetric_binding_commons(
    rp_asymmetric_binding_t *asymmetric_binding,
    const axutil_env_t *env,
    rp_symmetric_asymmetric_binding_commons_t * symmetric_asymmetric_binding_commons)
{
    AXIS2_PARAM_CHECK(env->error, symmetric_asymmetric_binding_commons, AXIS2_FAILURE);

    asymmetric_binding->symmetric_asymmetric_binding_commons = symmetric_asymmetric_binding_commons;
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN rp_property_t *AXIS2_CALL
rp_asymmetric_binding_get_initiator_token(
    rp_asymmetric_binding_t *asymmetric_binding,
    const axutil_env_t *env)
{
    return asymmetric_binding->initiator_token;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
rp_asymmetric_binding_set_initiator_token(
    rp_asymmetric_binding_t *asymmetric_binding,
    const axutil_env_t *env,
    rp_property_t *initiator_token)
{
    AXIS2_PARAM_CHECK(env->error, initiator_token, AXIS2_FAILURE);

    rp_property_increment_ref(initiator_token, env);
    asymmetric_binding->initiator_token = initiator_token;
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
rp_asymmetric_binding_set_recipient_token(
    rp_asymmetric_binding_t *asymmetric_binding,
    const axutil_env_t *env,
    rp_property_t *recipient_token)
{
    AXIS2_PARAM_CHECK(env->error, recipient_token, AXIS2_FAILURE);

    rp_property_increment_ref(recipient_token, env);
    asymmetric_binding->recipient_token = recipient_token;
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN rp_property_t *AXIS2_CALL
rp_asymmetric_binding_get_recipient_token(
    rp_asymmetric_binding_t *asymmetric_binding,
    const axutil_env_t *env)
{
    return asymmetric_binding->recipient_token;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
rp_asymmetric_binding_increment_ref(
    rp_asymmetric_binding_t *asymmetric_binding,
    const axutil_env_t *env)
{
    asymmetric_binding->ref++;
    return AXIS2_SUCCESS;
}
