/*
 * 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 <axutil_property.h>
#include <stdio.h>

struct axutil_property
{
    axis2_scope_t scope;
    AXIS2_FREE_VOID_ARG free_func;
    void *value;
    axis2_bool_t own_value;
};

axutil_property_t *AXIS2_CALL
axutil_property_create(
    const axutil_env_t * env)
{
    axutil_property_t *property = NULL;

    AXIS2_ENV_CHECK(env, NULL);

    property = (axutil_property_t *)AXIS2_MALLOC(env->allocator, sizeof(axutil_property_t));

    if(!property)
    {
        AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
        return NULL;
    }
    property->value = NULL;
    property->scope = AXIS2_SCOPE_REQUEST;
    property->free_func = 0;
    property->own_value = AXIS2_TRUE;

    return property;
}

/*****************************************************************************/
axutil_property_t *AXIS2_CALL
axutil_property_create_with_args(
    const axutil_env_t * env,
    axis2_scope_t scope,
    axis2_bool_t own_value,
    AXIS2_FREE_VOID_ARG free_func,
    void *value)
{
    axutil_property_t *property = NULL;

    AXIS2_ENV_CHECK(env, NULL);

    property = (axutil_property_t *)axutil_property_create(env);

    if(!property)
    {
        AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
        return NULL;
    }
    property->value = value;
    property->scope = scope;
    property->own_value = own_value;
    property->free_func = free_func;

    return property;
}

void AXIS2_CALL
axutil_property_free(
    axutil_property_t * property,
    const axutil_env_t * env)
{
    AXIS2_ENV_CHECK(env, AXIS2_FAILURE);
    AXIS2_PARAM_CHECK(env->error, property,);

    if(property->value)
    {
        if(property->scope != AXIS2_SCOPE_APPLICATION)
        {
            if(property->free_func && property->own_value)
            {
                property->free_func(property->value, env);
            }
            else if(property->own_value)
            {
                AXIS2_FREE(env->allocator, property->value);
            }
        }
    }

    if(property)
    {
        AXIS2_FREE(env->allocator, property);
    }
    return;
}

axis2_status_t AXIS2_CALL
axutil_property_set_scope(
    axutil_property_t * property,
    const axutil_env_t * env,
    axis2_scope_t scope)
{
    AXIS2_ENV_CHECK(env, AXIS2_FAILURE);

    property->scope = scope;
    return AXIS2_SUCCESS;
}

axis2_status_t AXIS2_CALL
axutil_property_set_free_func(
    axutil_property_t * property,
    const axutil_env_t * env,
    AXIS2_FREE_VOID_ARG free_func)
{
    AXIS2_ENV_CHECK(env, AXIS2_FAILURE);

    property->free_func = free_func;
    return AXIS2_SUCCESS;
}

axis2_status_t AXIS2_CALL
axutil_property_set_value(
    axutil_property_t * property,
    const axutil_env_t * env,
    void *value)
{
    AXIS2_ENV_CHECK(env, AXIS2_FAILURE);
    AXIS2_PARAM_CHECK(env->error, property, AXIS2_FAILURE);

    if(property->value)
    {
        if(property->scope != AXIS2_SCOPE_APPLICATION)
        {
            if(property->free_func && property->own_value)
            {
                property->free_func(property->value, env);
            }
            else if(property->own_value)
            {
                AXIS2_FREE(env->allocator, property->value);
            }
        }
    }

    property->value = value;
    return AXIS2_SUCCESS;
}

void *AXIS2_CALL
axutil_property_get_value(
    axutil_property_t * property,
    const axutil_env_t * env)
{
    return property->value;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
axutil_property_set_own_value(
    axutil_property_t * property,
    const axutil_env_t * env,
    axis2_bool_t own_value)
{
    AXIS2_ENV_CHECK(env, AXIS2_FAILURE);

    property->own_value = own_value;
    return AXIS2_SUCCESS;
}

axutil_property_t *AXIS2_CALL
axutil_property_clone(
    axutil_property_t * property,
    const axutil_env_t * env)
{
    axutil_property_t *new_property = NULL;
    AXIS2_ENV_CHECK(env, NULL);
    new_property = axutil_property_create(env);
    axutil_property_set_free_func(new_property, env, property->free_func);
    axutil_property_set_scope(new_property, env, property->scope);
    axutil_property_set_own_value(new_property, env, property->own_value);
    axutil_property_set_value(new_property, env, property->value);
    return new_property;
}


AXIS2_EXTERN axis2_scope_t AXIS2_CALL
axutil_property_get_scope(
	axutil_property_t *prop,
	const axutil_env_t *env)
{
	return prop->scope;
}

