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

#ifndef AXIOM_ELEMENT_INTERNAL_H_
#define AXIOM_ELEMENT_INTERNAL_H_

/** @defgroup axiom AXIOM (Axis Object Model)
 * @ingroup axis2
 * @{
 */

/** @} */

#include <axiom_element.h>

#ifdef __cplusplus
extern "C"
{
#endif

    /**
     * @defgroup axiom_element element
     * @ingroup axiom
     * @{
     */

    /**
     * Collect all the namespaces with distinct prefixes in the parents of the given element.
     * Effectively this is the set of namespaces declared above this element that are inscope at
     * this element and might be used by it or its children.
     * @param om_element pointer to om_element
     * @param env environment MUST not be NULL
     * @param om_node pointer to this element node
     * @returns pointer to hash of relevant namespaces
     */
    axutil_hash_t * AXIS2_CALL
    axiom_element_gather_parent_namespaces(
        axiom_element_t * om_element,
        const axutil_env_t * env,
        axiom_node_t * om_node);

    /**
     * Examines the subtree beginning at the provided element for each element or attribute,
     * if it refers to a namespace declared in a parent of the subtree root element, if not already
     * declared, redeclares that namespace at the level of the subtree root and removes
     * it from the set of parent inscope_namespaces. inscope_namespaces contains all the parent
     * namespaces which should be redeclared at some point.
     * @param om_element pointer to om_element
     * @param env environment MUST not be NULL
     * @param om_node pointer to this element node
     * @param inscope_namespaces pointer to hash of parent namespaces
     */
    void AXIS2_CALL
    axiom_element_redeclare_parent_namespaces(
        axiom_element_t * om_element,
        const axutil_env_t * env,
        axiom_node_t * om_node,
        axutil_hash_t *inscope_namespaces);

    /**
     * If the provided namespace used by the provided element is one of the namespaces from the
     * parent of the root element, redeclares that namespace at the root element and removes it
     * from the hash of parent namespaces
     * @param om_element pointer to om_element
     * @param env environment MUST not be NULL
     * @param om_node pointer to this element node
     * @param ns pointer to namespace to redeclare
     * @param inscope_namespaces pointer to hash of parent namespaces
     */
    void AXIS2_CALL
    axiom_element_use_parent_namespace(
        axiom_element_t * om_element,
        const axutil_env_t * env,
        axiom_node_t * om_node,
        axiom_namespace_t *ns,
        axutil_hash_t *inscope_namespaces);

    /**
     * retrieves the default namespace of this element
     * @param om_element pointer to om element
     * @param env axutil_environment MUST Not be NULL
     * @param element_node corresponding om element node of this om element
     * @returns pointer to default namespace if available , NULL otherwise
     */
    axiom_namespace_t *AXIS2_CALL
    axiom_element_get_default_namespace(
        axiom_element_t * om_element,
        const axutil_env_t * env,
        axiom_node_t * element_node);

    /**
     * Serializes the start part of the given element
     * @param element element to be serialized.
     * @param env Environment. MUST NOT be NULL.
     * @param om_output AXIOM output handler to be used in serializing
     * @return status of the operation. AXIS2_SUCCESS on success else AXIS2_FAILURE
     */
    axis2_status_t AXIS2_CALL
    axiom_element_serialize_start_part(
        axiom_element_t * om_element,
        const axutil_env_t * env,
        axiom_output_t * om_output,
        axiom_node_t * ele_node);

    /**
     * Serializes the end part of the given element. serialize_start_part must
     *     have been called before calling this method.
     * @param om_element pointer to om_element
     * @param env environment MUST not be NULL
     * @param om_node pointer to this element node
     * @param om_output AXIOM output handler to be used in serializing
     * @return status of the operation. AXIS2_SUCCESS on success else AXIS2_FAILURE
     */
    axis2_status_t AXIS2_CALL
    axiom_element_serialize_end_part(
        axiom_element_t * om_element,
        const axutil_env_t * env,
        axiom_output_t * om_output);

    /**
     * Set whether the element is empty or not
     * @param om_element pointer to om_element
     * @param env environment MUST not be NULL
     * @param is_empty AXIS2_TRUE if empty AXIS2_FALSE if not empty
     * @return VOID
     */
    void AXIS2_CALL
    axiom_element_set_is_empty(
        axiom_element_t * om_element,
        const axutil_env_t * env,
        axis2_bool_t is_empty);

	AXIS2_EXTERN axis2_bool_t AXIS2_CALL
	axiom_element_get_is_empty(
		axiom_element_t * om_element,
		const axutil_env_t * env);

#endif /* AXIOM_ELEMENT_INTERNAL_H_ */
