/*
 * 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.
 */
#if !defined(XALAN_ELEMEMPTY_HEADER_GUARD)
#define XALAN_ELEMEMPTY_HEADER_GUARD 

/**
 * Simple empty elem to push on the stack when nothing 
 * else got pushed, so that pop() works correctly.
 */

// Base include file.  Must be first.
#include "XSLTDefinitions.hpp"



// Base class header file.
#include "ElemTemplateElement.hpp"



namespace XALAN_CPP_NAMESPACE {



class ElemEmpty : public ElemTemplateElement
{
public:

    /**
     * Construct an object corresponding to an empty element
     * 
     * @param constructionContext context for construction of object
     * @param stylesheetTree      stylesheet containing element
     * @param lineNumber                line number in document
     * @param columnNumber          column number in document
     * @param elementName The element name for which this instance is representing
     */
    ElemEmpty(
            StylesheetConstructionContext&  constructionContext,
            Stylesheet&                     stylesheetTree,
            XalanFileLoc                    lineNumber, 
            XalanFileLoc                    columnNumber,
            const XalanDOMString*           elementName = 0);

    /**
     * Construct an object corresponding to an empty element.  This
     * constructor is used for surrogate empty elements that do not
     * need namespace contexts and Locator information, etc.
     *
     * @param constructionContext context for construction of object
     * @param stylesheetTree      stylesheet containing element
     * @param elementName The element name for which this instance is representing
     */
    ElemEmpty(
            StylesheetConstructionContext&  constructionContext,
            Stylesheet&                     stylesheetTree,
            const XalanDOMString*           elementName = 0);

    virtual
    ~ElemEmpty();

    // These methods are inherited from ElemTemplateElement ...
    
    virtual const XalanDOMString&
    getElementName() const;

#if !defined(XALAN_RECURSIVE_STYLESHEET_EXECUTION)
    virtual const ElemTemplateElement*
    startElement(StylesheetExecutionContext&    executionContext) const;
#else
    virtual void
    execute(StylesheetExecutionContext&     executionContext) const;
#endif

protected:

    virtual bool
    childTypeAllowed(int    xslToken) const;

private:

    const XalanDOMString* const     m_elementName;
};



}



#endif  // XALAN_ELEMEMPTY_HEADER_GUARD
