// file      : xsd/cxx/xml/dom/parser.hxx
// author    : Boris Kolpackov <boris@codesynthesis.com>
// copyright : Copyright (c) 2005-2006 Code Synthesis Tools CC
// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file

#ifndef XSD_CXX_XML_DOM_PARSER_HXX
#define XSD_CXX_XML_DOM_PARSER_HXX

#include <cassert>

#include <xsd/cxx/xml/dom/elements.hxx>

namespace xsd
{
  namespace cxx
  {
    namespace xml
    {
      namespace dom
      {
        template <typename C>
        class parser
        {
        public:
          parser (element<C> const& e)
              : e_ (e.dom_element ()->getChildNodes ()), ei_ (0),
                a_ (e.dom_element ()->getAttributes ()), ai_ (0)
          {
            find_next_element ();
          }

          bool
          more_elements () const
          {
            return e_->getLength () > ei_;
          }

          element<C>
          next_element ()
          {
            using xercesc::DOMNode;

            DOMNode* n (e_->item (ei_++));
            assert (n->getNodeType () == DOMNode::ELEMENT_NODE);

            find_next_element ();

            return element<C> (static_cast<xercesc::DOMElement*> (n));
          }

          bool
          more_attributes () const
          {
            return a_->getLength () > ai_;
          }

          attribute<C>
          next_attribute ()
          {
            using xercesc::DOMNode;

            DOMNode* n (a_->item (ai_++));
            assert (n->getNodeType () == DOMNode::ATTRIBUTE_NODE);

            return attribute<C> (static_cast<xercesc::DOMAttr*> (n));
          }

        private:
          void
          find_next_element ()
          {
            using xercesc::DOMNode;

            for (; ei_ < e_->getLength () &&
                   e_->item (ei_)->getNodeType () != DOMNode::ELEMENT_NODE;
                 ++ei_);
          }

        private:
          parser (parser const&);

          parser&
          operator= (parser const&);

        private:
          xercesc::DOMNodeList const* e_;
          unsigned long ei_; // Index of the next DOMElement.

          xercesc::DOMNamedNodeMap const* a_;
          unsigned long ai_; // Index of the next DOMAttr.
        };
      }
    }
  }
}

#endif // XSD_CXX_XML_DOM_PARSER_HXX
