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

struct neethi_reference_t
{
    axis2_char_t *uri;
};

AXIS2_EXTERN neethi_reference_t *AXIS2_CALL
neethi_reference_create(
    const axutil_env_t *env)
{
    neethi_reference_t *neethi_reference = NULL;

    AXIS2_ENV_CHECK(env, NULL);

    neethi_reference = (neethi_reference_t *)AXIS2_MALLOC(env->allocator,
        sizeof(neethi_reference_t));

    if(neethi_reference == 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_reference->uri = NULL;

    return neethi_reference;
}

AXIS2_EXTERN void AXIS2_CALL
neethi_reference_free(
    neethi_reference_t *neethi_reference,
    const axutil_env_t *env)
{
    if(neethi_reference)
    {
        AXIS2_FREE(env->allocator, neethi_reference);
        neethi_reference = NULL;
    }
    return;
}

/* Implementations */

AXIS2_EXTERN axis2_char_t *AXIS2_CALL
neethi_reference_get_uri(
    neethi_reference_t *neethi_reference,
    const axutil_env_t *env)
{
    return neethi_reference->uri;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
neethi_reference_set_uri(
    neethi_reference_t *neethi_reference,
    const axutil_env_t *env,
    axis2_char_t *uri)
{
    neethi_reference->uri = uri;
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
neethi_reference_serialize(
    neethi_reference_t *neethi_reference,
    axiom_node_t *parent,
    const axutil_env_t *env)
{
    axiom_node_t *ref_node = NULL;
    axiom_element_t *ref_ele = NULL;
    axiom_namespace_t *policy_ns = NULL;
    axiom_attribute_t *att_uri = NULL;

    policy_ns = axiom_namespace_create(env, NEETHI_NAMESPACE, NEETHI_PREFIX);
    ref_ele = axiom_element_create(env, parent, NEETHI_REFERENCE, policy_ns, &ref_node);
    if(!ref_node)
    {
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
            "'reference' node creation failed. Cannot serialize 'reference' assertion");
        return AXIS2_FAILURE;
    }

    att_uri = axiom_attribute_create(env, NEETHI_URI, neethi_reference->uri, NULL);
    axiom_element_add_attribute(ref_ele, env, att_uri, ref_node);

    return AXIS2_SUCCESS;
}
