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

struct neethi_registry_t
{
    axutil_hash_t *registry;
    neethi_registry_t *parent;
};

AXIS2_EXTERN neethi_registry_t *AXIS2_CALL
neethi_registry_create(
    const axutil_env_t *env)
{
    neethi_registry_t *neethi_registry = NULL;

    AXIS2_ENV_CHECK(env, NULL);

    neethi_registry = (neethi_registry_t *) AXIS2_MALLOC(env->allocator,
                                                         sizeof
                                                         (neethi_registry_t));

    if (neethi_registry == 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_registry->registry = NULL;

    neethi_registry->registry = axutil_hash_make(env);
    if (!(neethi_registry->registry))
    {
        neethi_registry_free(neethi_registry, 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;
    }
    neethi_registry->parent = NULL;

    return neethi_registry;
}

AXIS2_EXTERN neethi_registry_t *AXIS2_CALL
neethi_registry_create_with_parent(
    const axutil_env_t *env,
    neethi_registry_t *parent)
{
    neethi_registry_t *neethi_registry = NULL;

    neethi_registry = neethi_registry_create(env);
    if (!neethi_registry)
        return NULL;

    neethi_registry->parent = parent;
    return neethi_registry;
}

AXIS2_EXTERN void AXIS2_CALL
neethi_registry_free(
    neethi_registry_t *neethi_registry,
    const axutil_env_t *env)
{
    if (neethi_registry->registry)
    {
        axutil_hash_index_t *hi = NULL;
        void *val = NULL;
        for (hi = axutil_hash_first(neethi_registry->registry, env); hi;
             hi = axutil_hash_next(env, hi))
        {
            neethi_policy_t *neethi_policy = NULL;
            axutil_hash_this(hi, NULL, NULL, &val);
            neethi_policy = (neethi_policy_t *) val;
            if (neethi_policy)
                neethi_policy_free(neethi_policy, env);
            val = NULL;
            neethi_policy = NULL;

        }
        axutil_hash_free(neethi_registry->registry, env);
    }
    if (neethi_registry->parent)
    {
        neethi_registry->parent = NULL;
    }
    AXIS2_FREE(env->allocator, neethi_registry);
}

/* Implementations */

AXIS2_EXTERN axis2_status_t AXIS2_CALL
neethi_registry_register(
    neethi_registry_t *neethi_registry,
    const axutil_env_t *env,
    axis2_char_t *key,
    neethi_policy_t *value)
{
    axutil_hash_set(neethi_registry->registry, key, AXIS2_HASH_KEY_STRING,
                    value);
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN neethi_policy_t *AXIS2_CALL
neethi_registry_lookup(
    neethi_registry_t *neethi_registry,
    const axutil_env_t *env,
    axis2_char_t *key)
{
    neethi_policy_t *policy = NULL;

    policy = (neethi_policy_t *) axutil_hash_get(neethi_registry->registry, key,
                                                 AXIS2_HASH_KEY_STRING);

    if (!policy && neethi_registry->parent)
    {
        return neethi_registry_lookup(neethi_registry->parent, env, key);
    }
    return policy;
}
