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

#ifndef XSD_CXX_TREE_ELEMENTS_HXX
#define XSD_CXX_TREE_ELEMENTS_HXX

#include <map>
#include <string>
#include <vector>
#include <istream>
#include <ostream>
#include <sstream>
#include <memory>  // std::auto_ptr

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

#include <xsd/cxx/tree/exceptions.hxx>

namespace xsd
{
  namespace cxx
  {
    namespace tree
    {
      //
      //
      struct flags
      {
        // Use the following flags to modify the default behavior
        // of the parsing funtions.
        //

        // Keep DOM association in the resulting tree. Useful for
        // dealing with "type-less" content such as mixed content
        // models, any/anyAttribute, and anyType/anySimpleType.
        //
        static unsigned long const keep_dom = 0x00000001;

        // Do not try to validate instance docuemnts. Note that
        // the xsd runtime assumes instance documents are valid so
        // you had better make sure they are if you specify this flag.
        //
        //
        static unsigned long const dont_validate = 0x00000002;

        // Do not initialize Xerces-C++ runtime.
        //
        static unsigned long const dont_initialize = 0x00000004;


        // The following flags are for internal use.
        //
        static unsigned long const not_root = 0x00000008;

      public:
        flags (unsigned long x = 0)
            : x_ (x)
        {
        }

        operator unsigned long () const
        {
          return x_;
        }

      private:
        unsigned long x_;
      };


      //
      //
      struct identity
      {
        virtual
        ~identity ()
        {
        }

        identity ()
        {
        }

        virtual bool
        before (identity const&) const = 0;

        virtual void
        throw_duplicate_id () const = 0;

      private:
        identity (identity const&);

        identity&
        operator= (identity const&);
      };


      // anyType
      //
      class type
      {
      public:
        virtual
        ~type ()
        {
          // Everyhting should have been unregistered by now.
          //
          assert (map_.get () == 0 || map_->size () == 0);
        }

      public:
        type ()
            : container_ (0)
        {
        }

        template <typename C>
        type (xml::dom::element<C> const& e, flags f, type* container)
            : dom_info_ (dom_info_factory::create (e, f)),
              container_ (container)
        {
        }

        template <typename C>
        type (xml::dom::attribute<C> const& a, flags f, type* container)
            : dom_info_ (dom_info_factory::create (a, f)),
              container_ (container)
        {
        }

        template <typename C>
        type (std::basic_string<C> const&,
              xml::dom::element<C> const&,
              flags,
              type* container)
            : dom_info_ (0), // List elements don't have associated DOM nodes.
              container_ (container)
        {
        }

        type (type const& t, flags f = 0, type* container = 0)
            : dom_info_ (t.dom_info_.get ()
                         ? t.dom_info_->clone (f, container)
                         : std::auto_ptr<dom_info> (0)),
            container_ (container)
        {
        }

      public:
        type&
        operator= (type const&)
        {
          return *this;
        }

        // Container API.
        //
      public:
        type const*
        _container () const
        {
          return container_ ? container_ : this;
        }

        type*
        _container ()
        {
          return container_ ? container_ : this;
        }


        type const*
        _root () const
        {
          type const* r (_container ());

          for (type const* c = r->_container ();
               c != r;
               c = c->_container ())
            r = c;

          return r;
        }

        type*
        _root ()
        {
          type* r (_container ());

          for (type* c = r->_container (); c != r; c = c->_container ())
            r = c;

          return r;
        }

      public:
        /*
        virtual void
        container (type* c)
        {
          if (container_ == c)
            return;

          // Revoke registrations from our ex-container.
          //
          if (container_ != 0 && map_.get ())
          {
            for (map::iterator i (map_->begin ()); i != map_->end (); ++i)
            {
              //std::wcerr << "revoking " << i->second
              //           << " to " << container_ << std::endl;

              container_->unregister_id (*(i->first));
            }
          }

          // Copy registrations to our new container.
          //
          if (c != 0 && map_.get ())
          {
            for (map::iterator i (map_->begin ()); i != map_->end (); ++i)
            {
              //std::wcerr << "copying " << i->second
              //           << " to " << c << std::endl;

              c->register_id (*(i->first), i->second);
            }
          }

          container_  = c;
        }
        */

      public:
        void
        _register_id (identity const& id, type* t)
        {
          if (map_.get () == 0)
            map_ = std::auto_ptr<map> (new map);

          if (!map_->insert (
                std::pair<identity const*, type*> (&id, t)).second)
          {
            id.throw_duplicate_id ();
          }

          if (_container () != this)
	    _container ()->_register_id (id, t);
        }

        //
        //
        struct not_registered: virtual exception
        {
          virtual char const*
          what () const throw ()
          {
            return "attempt to unregister non-existent id";
          }
        };

        void
        _unregister_id (identity const& id)
        {
          if (map_.get ())
          {
            map::iterator it (map_->find (&id));

            if (it != map_->end ())
            {
              map_->erase (it);

              if (_container () != this)
	        _container ()->_unregister_id (id);

              return;
            }
          }

          throw not_registered ();
        }

        type*
        _lookup_id (identity const& id) const
        {
          if (map_.get ())
          {
            map::const_iterator it (map_->find (&id));

            if (it != map_->end ())
              return it->second;
          }

          return 0;
        }

        // DOM association.
        //
      public:
        xercesc::DOMNode const*
        _node () const
        {
          return dom_info_.get () ? dom_info_->node() : 0;
        }

        xercesc::DOMNode*
        _node ()
        {
          return dom_info_.get () ? dom_info_->node () : 0;
        }

      private:
        struct dom_info
        {
          virtual
          ~dom_info ()
          {
          }

          dom_info ()
          {
          }

          virtual std::auto_ptr<dom_info>
          clone (flags f, type* c) const = 0;

          virtual xercesc::DOMNode*
          node () = 0;

        private:
          dom_info (dom_info const&);

          dom_info&
          operator= (dom_info const&);
        };


        struct dom_element_info: public dom_info
        {
          dom_element_info (xercesc::DOMElement& e, flags f)
              : doc_ ((f & flags::not_root) ? 0 : e.getOwnerDocument ()),
                e_ (e)
          {
            assert (f & flags::keep_dom);
          }

          virtual std::auto_ptr<dom_info>
          clone (flags f, type* c) const
          {
            using std::auto_ptr;

            if ((f & flags::not_root) == 0)
            {
              // We preserver DOM associations only in complete
              // copies from root.
              //
              if (doc_.get () == 0)
                return auto_ptr<dom_info> (0);

              return auto_ptr<dom_info> (new dom_element_info (*doc_));
            }

            // We are not a root node so container shouldn't be 0.
            //
            assert (c != 0);


            // Now we are going to find the corresponding element in
            // the new tree.
            //
            {
              using xercesc::DOMElement;
              using xercesc::DOMNodeList;

              DOMElement& p (
                dynamic_cast<DOMElement&> (*e_.getParentNode ()));

              DOMNodeList& nl (*p.getChildNodes ());

              XMLSize_t size (nl.getLength ()), i (0);

              // We should have at least one child.
              //
              assert (size != 0);

              for ( ;i < size && !e_.isSameNode (nl.item (i)); ++i);

              // e_ should be in the list.
              //
              assert (i < size);

              return auto_ptr<dom_info> (
                new dom_element_info (
                  dynamic_cast<DOMElement&> (
                    *c->_node ()->getChildNodes ()->item (i)),
                  f | flags::keep_dom));
            }
          }

          virtual xercesc::DOMNode*
          node ()
          {
            return &e_;
          }

        private:
          dom_element_info (xercesc::DOMDocument const& d)
              : doc_ (dynamic_cast<xercesc::DOMDocument*> (
                        d.cloneNode (true))),
                e_ (*doc_->getDocumentElement ())
          {
          }

        private:
          xml::dom::auto_ptr<xercesc::DOMDocument> doc_;
          xercesc::DOMElement& e_;
        };


        struct dom_attribute_info: public dom_info
        {
          dom_attribute_info (xercesc::DOMAttr& a, flags f)
              : a_ (a)
          {
            assert (f & flags::not_root);
            assert (f & flags::keep_dom);
          }

          virtual std::auto_ptr<dom_info>
          clone (flags f, type* c) const
          {
            using std::auto_ptr;

            if ((f & flags::not_root) == 0)
            {
              // We preserver DOM associations only in complete
              // copies from root.
              //
              return auto_ptr<dom_info> (0);
            }

            // We are not a root node so container shouldn't be 0.
            //
            assert (c != 0);

            // We are going to find the corresponding attribute in
            // the new tree.
            //
            using xercesc::DOMAttr;
            using xercesc::DOMElement;
            using xercesc::DOMNamedNodeMap;

            DOMElement& p (*a_.getOwnerElement ());
            DOMNamedNodeMap& nl (*p.getAttributes ());

            XMLSize_t size (nl.getLength ()), i (0);

            // We should have at least one child.
            //
            assert (size != 0);

            for ( ;i < size && !a_.isSameNode (nl.item (i)); ++i);

            // a_ should be in the list.
            //
            assert (i < size);

            return auto_ptr<dom_info> (
              new dom_attribute_info (
                dynamic_cast<DOMAttr&> (
                  *c->_node ()->getAttributes ()->item (i)),
                f | flags::keep_dom));
          }

          virtual xercesc::DOMNode*
          node ()
          {
            return &a_;
          }

        private:
          xercesc::DOMAttr& a_;
        };


        struct dom_info_factory
        {
          template <typename C>
          static std::auto_ptr<dom_info>
          create (xml::dom::element<C> const& e, flags f)
          {
            using std::auto_ptr;

            if ((f & flags::keep_dom) == 0)
              return auto_ptr<dom_info> (0);

            return auto_ptr<dom_info> (
              new dom_element_info (
                const_cast<xercesc::DOMElement&> (*e.dom_element ()), f));
          }

          template <typename C>
          static std::auto_ptr<dom_info>
          create (xml::dom::attribute<C> const& a, flags f)
          {
            using std::auto_ptr;

            if ((f & flags::keep_dom) == 0)
              return auto_ptr<dom_info> (0);

            return auto_ptr<dom_info> (
              new dom_attribute_info (
                const_cast<xercesc::DOMAttr&> (*a.dom_attribute ()), f));
          }
        };


        std::auto_ptr<dom_info> dom_info_;


        // ID/IDREF map.
        //
      private:
        struct identity_comparator
        {
          bool operator () (identity const* x, identity const* y) const
          {
            return x->before (*y);
          }
        };

        typedef
        std::map<identity const*, type*, identity_comparator>
        map;

        std::auto_ptr<map> map_;

      private:
        type* container_;
      };

      template <typename C>
      inline std::basic_ostream<C>&
      operator<< (std::basic_ostream<C>& os, type const&)
      {
        return os;
      }


      // anySimpleType
      //
      class simple_type: public type
      {
      public:
        simple_type ()
        {
        }

        template <typename C>
        simple_type (xml::dom::element<C> const& e, flags f, type* container)
            : type (e, f, container)
        {
        }

        template <typename C>
        simple_type (xml::dom::attribute<C> const& a,
                     flags f,
                     type* container)
            : type (a, f, container)
        {
        }

        template <typename C>
        simple_type (std::basic_string<C> const& s,
                     xml::dom::element<C> const& e,
                     flags f,
                     type* container)
            : type (s, e, f, container)
        {
        }

        simple_type (simple_type const& other,
                     flags f = 0,
                     type* container = 0)
            : type (other, f, container)
        {
        }
      };

      template <typename C>
      inline std::basic_ostream<C>&
      operator<< (std::basic_ostream<C>& os, simple_type const&)
      {
        return os;
      }

      //
      //
      template <typename T>
      struct traits
      {
        static bool
        same_container (T& i, type* c)
        {
          return i._container () == c;
        }

        template <typename C>
        static std::auto_ptr<T>
        create (xml::dom::element<C> const& e,
                flags f,
                type* container)
        {
          return std::auto_ptr<T> (new T (e, f, container));
        }

        template <typename C>
        static std::auto_ptr<T>
        create (xml::dom::attribute<C> const& a,
                flags f,
                type* container)
        {
          return std::auto_ptr<T> (new T (a, f, container));
        }

        template <typename C>
        static std::auto_ptr<T>
        create (std::basic_string<C> const& s,
                xml::dom::element<C> const& parent,
                flags f,
                type* container)
        {
          return std::auto_ptr<T> (new T (s, parent, f, container));
        }

        static std::auto_ptr<T>
        clone (T const& other, flags f, type* container)
        {
          return std::auto_ptr<T> (new T (other, f, container));
        }
      };


      // Containers.
      //


      //
      //
      template <typename X>
      class optional
      {
      public:
        explicit
        optional (flags f = 0, type* c = 0)
            : flags_ (f), container_ (c)
        {
        }

        optional (optional const& y, flags f = 0, type* c = 0)
            : flags_ (f), container_ (c)
        {
          if (y)
            set (*y);
        }

        /*
        template <typename Y>
        optional (optional<Y> const& y)
        {
        }
        */

        optional&
        operator= (optional const& y)
        {
          if (x_.get () == y.x_.get ())
            return *this;

          if (y)
            set (*y);
          else
            reset ();

          return *this;
        }

        /*
        template <typename Y>
        optional_iterator&
        operator= (optional_iterator<Y> const& y)
        {
          return *this;
        }
        */

        // Pointer-like interface.
        //
      public:
        X const*
        operator-> () const
        {
          return x_.get ();
        }

        X*
        operator-> ()
        {
          return x_.get ();
        }

        X const&
        operator* () const
        {
          return get ();
        }

        X&
        operator* ()
        {
          return get ();
        }

        typedef void (optional::*bool_convertible) ();

        operator bool_convertible () const
        {
          return present () ? &optional::reset : 0;
        }

        // Get/set interface.
        //
      public:
        bool
        present () const
        {
          return x_.get () != 0;
        }

        X const&
        get () const
        {
          return *x_;
        }

        X&
        get ()
        {
          return *x_;
        }

        void
        set (X const& y)
        {
          if (x_.get () != 0)
            *x_ = y;
          else
            x_ = traits<X>::clone (y, flags_, container_);
        }

        void
        set (std::auto_ptr<X> y)
        {
          if (y.get () == 0)
            reset ();
          else
          {
            if (traits<X>::same_container (*y, container_))
              x_ = y;
            else
              set (*y);
          }
        }

        void
        reset ()
        {
          x_.reset ();
        }

      private:
        template <typename>
        friend class optional;

      private:
        flags flags_;
        type* container_;
        std::auto_ptr<X> x_;
      };


      // sequence
      //

      // Test whether X is a C++ fundamental type.
      //
      template <typename X>
      struct fundamental_p
      {
        static bool const r = false;
      };

      // byte
      //
      template <>
      struct fundamental_p<signed char>
      {
        static bool const r = true;
      };

      template <>
      struct fundamental_p<unsigned char>
      {
        static bool const r = true;
      };

      // short
      //
      template <>
      struct fundamental_p<short>
      {
        static bool const r = true;
      };

      template <>
      struct fundamental_p<unsigned short>
      {
        static bool const r = true;
      };

      // int
      //
      template <>
      struct fundamental_p<int>
      {
        static bool const r = true;
      };

      template <>
      struct fundamental_p<unsigned int>
      {
        static bool const r = true;
      };

      // long
      //
      template <>
      struct fundamental_p<long>
      {
        static bool const r = true;
      };

      template <>
      struct fundamental_p<unsigned long>
      {
        static bool const r = true;
      };

      template <>
      struct fundamental_p<long long>
      {
        static bool const r = true;
      };

      template <>
      struct fundamental_p<unsigned long long>
      {
        static bool const r = true;
      };

      // bool
      //
      template <>
      struct fundamental_p<bool>
      {
        static bool const r = true;
      };

      // float
      //
      template <>
      struct fundamental_p<float>
      {
        static bool const r = true;
      };

      template <>
      struct fundamental_p<double>
      {
        static bool const r = true;
      };

      template <>
      struct fundamental_p<long double>
      {
        static bool const r = true;
      };


      //@@ Complete emulation of std::vector.
      //

      template <typename X, bool fundamental = tree::fundamental_p<X>::r>
      class sequence;


      // Specialization for complex types.
      //

      // Seven years since 1998, Sun still uses raw pointers for
      // iterators. Sun, what a pathetic company you are!
      //
      template <typename I>
      struct iterator_to_value
      {
        typedef typename I::value_type r;
      };

      template <typename I>
      struct iterator_to_value<I*>
      {
        typedef I r;
      };

      template <typename I>
      struct iterator_adapter
      {
        typedef I base_iterator;
        typedef typename iterator_to_value<I>::r::value value;
        typedef value& reference;
        typedef value* pointer;

        explicit
        iterator_adapter (I const& i)
            : i_ (i)
        {
        }

        // Allow iterator to const_iterator conversion.
        //
        template <typename J>
        iterator_adapter (iterator_adapter<J> const& j)
            : i_ (j.base ())
        {
        }

      public:
        reference
        operator* () const
        {
          return **i_;
        }

        pointer
        operator-> () const
        {
          return i_->get ();
        }

      public:
        I const&
        base () const
        {
          return i_;
        }

      public:
        iterator_adapter&
        operator++ ()
        {
          ++i_;
          return *this;
        }

        iterator_adapter
        operator++ (int)
        {
          iterator_adapter r (*this);
          ++i_;
          return r;
        }

        iterator_adapter&
        operator-- ()
        {
          --i_;
          return *this;
        }

        iterator_adapter
        operator-- (int)
        {
          iterator_adapter r (*this);
          --i_;
          return r;
        }

      private:
        I i_;
      };

      // Note: We use different types for left- and right-hand-side
      // arguments to allow comparison between iterator and const_iterator.
      //

      template <typename I, typename J>
      inline bool
      operator== (iterator_adapter<I> const& i, iterator_adapter<J> const& j)
      {
        return i.base () == j.base ();
      }

      template <typename I, typename J>
      inline bool
      operator!= (iterator_adapter<I> const& i, iterator_adapter<J> const& j)
      {
        return i.base () != j.base ();
      }

      template <typename I, typename J>
      inline typename iterator_adapter<I>::base_iterator::difference_type
      operator- (iterator_adapter<I> const& i, iterator_adapter<I> const& j)
      {
        return i.base () - j.base ();
      }

      template <typename X>
      class sequence<X, false>
      {
        // This is a dangerously destructive automatic pointer. We are going
        // to use it in a controlled environment to save us a lot of coding.
        //
        struct ptr
        {
          typedef X value;

          ~ptr ()
          {
            reset ();
          }

          explicit
          ptr (X* x = 0)
              : x_ (x)
          {
          }

          ptr (ptr const& y)
              : x_ (y.x_)
          {
            // Yes, hostile takeover.
            //
            y.x_ = 0;
          }

          ptr&
          operator= (ptr const& y)
          {
            if (this != &y)
            {
              // Yes, hostile takeover.
              //
              reset (y.x_);
              y.x_ = 0;
            }

            return *this;
          }

        public:
          X&
          operator* () const
          {
            return *get ();
          }

          X*
          get () const
          {
            return x_;
          }

        private:
          void
          reset (X* x = 0)
          {
            delete x_;
            x_ = x;
          }

        private:
          mutable X* x_;
        };

        typedef std::vector<ptr> base_sequence;
        typedef typename base_sequence::iterator base_iterator;
        typedef typename base_sequence::const_iterator base_const_iterator;

      public:
        typedef X        value_type;
        typedef X*       pointer;
        typedef X const* const_pointer;
        typedef X&       reference;
        typedef X const& const_reference;

        typedef
        iterator_adapter<typename base_sequence::iterator>
        iterator;

        typedef
        iterator_adapter<typename base_sequence::const_iterator>
        const_iterator;

        typedef
        iterator_adapter<typename base_sequence::reverse_iterator>
        reverse_iterator;

        typedef
        iterator_adapter<typename base_sequence::const_reverse_iterator>
        const_reverse_iterator;

        typedef typename base_sequence::size_type       size_type;
        typedef typename base_sequence::difference_type difference_type;
        typedef typename base_sequence::allocator_type  allocator_type;

      public:
        explicit
        sequence (flags f = 0, type* c = 0)
            : flags_ (f | flags::not_root), container_ (c)
        {
        }

        sequence (sequence const& v, flags f = 0, type* c = 0)
            : flags_ (f | flags::not_root), container_ (c), v_ (v.size ())
        {
          base_iterator di (v_.begin ()), de (v_.end ());
          base_const_iterator si (v.v_.begin ()), se (v.v_.end ());

          for (; si != se && di != de; ++si, ++di)
          {
            ptr p (new X (**si, flags_, container_)); // We have no ptr_ref.
            *di = p;
          }
        }

        sequence&
        operator= (sequence const& v)
        {
          if (this == &v)
            return *this;

          v_.assign (v.v_.size (), ptr ());

          base_iterator di (v_.begin ()), de (v_.end ());
          base_const_iterator si (v.v_.begin ()), se (v.v_.end ());

          for (; si != se && di != de; ++si, ++di)
          {
            ptr p (new X (**si, flags_, container_)); // We have no ptr_ref.
            *di = p;
          }

          return *this;
        }

      public:
        size_type
        size () const
        {
          return v_.size ();
        }

        size_type
        max_size () const
        {
          return v_.max_size ();
        }

        size_type
        capacity () const
        {
          return v_.capacity ();
        }

        bool
        empty () const
        {
          return v_.empty ();
        }

        void
        reserve (size_type n)
        {
          return v_.reserve (n);
        }

      public:
        const_iterator
        begin () const
        {
          return const_iterator (v_.begin ());
        }

        const_iterator
        end () const
        {
          return const_iterator (v_.end ());
        }

        iterator
        begin ()
        {
          return iterator (v_.begin ());
        }

        iterator
        end ()
        {
          return iterator (v_.end ());
        }

        // reverse
        //

        const_reverse_iterator
        rbegin () const
        {
          return const_reverse_iterator (v_.rbegin ());
        }

        const_reverse_iterator
        rend () const
        {
          return const_reverse_iterator (v_.rend ());
        }

        reverse_iterator
        rbegin ()
        {
          return reverse_iterator (v_.rbegin ());
        }

        reverse_iterator
        rend ()
        {
          return reverse_iterator (v_.rend ());
        }

      public:
        X&
        operator[] (size_type n)
        {
          return *(v_[n]);
        }

        X const&
        operator[] (size_type n) const
        {
          return *(v_[n]);
        }

        X&
        at (size_type n)
        {
          return *(v_.at (n));
        }

        X const&
        at (size_type n) const
        {
          return *(v_.at (n));
        }

        X&
        front ()
        {
          return *(v_.front ());
        }

        X const&
        front () const
        {
          return *(v_.front ());
        }

        X&
        back ()
        {
          return *(v_.back ());
        }

        X const&
        back () const
        {
          return *(v_.back ());
        }

      public:
        void
        push_back (X const& x)
        {
          v_.push_back (ptr (new X (x, flags_, container_)));
        }

        void
        push_back (std::auto_ptr<X> x)
        {
          if (traits<X>::same_container (*x, container_))
            v_.push_back (ptr (x.release ()));
          else
            push_back (*x);
        }


        void
        pop_back ()
        {
          v_.pop_back ();
        }

        iterator
        insert (iterator position, X const& x)
        {
          return iterator (
            v_.insert (
              position.base (), ptr (new X (x, flags_, container_))));
        }

        iterator
        erase (iterator position)
        {
          return iterator (v_.erase (position.base ()));
        }

        void
        clear ()
        {
          v_.clear ();
        }

        void
        swap (sequence& x)
        {
          v_.swap (x.v_);
        }

      public:

        // This c-tors are used only in xsd:list mapping. Individual
        // items of the list have no DOM association. Therefore I
        // clear keep_dom from flags.
        //

        template <typename C>
        explicit
        sequence (xml::dom::element<C> const& e, flags f, type* c)
            : flags_ ((f & ~flags::keep_dom) | flags::not_root),
              container_ (c)
        {
          init (e.value (), e);
        }

        template <typename C>
        explicit
        sequence (xml::dom::attribute<C> const& a, flags f, type* c)
            : flags_ ((f & ~flags::keep_dom) | flags::not_root),
              container_ (c)
        {
          init (a.value (), a.element ());
        }

        template <typename C>
        sequence (std::basic_string<C> const& s,
                  xml::dom::element<C> const& e,
                  flags f,
                  type* c)
            : flags_ ((f & ~flags::keep_dom) | flags::not_root),
              container_ (c)
        {
          init (s, e);
        }

      private:
        template <typename C>
        void
        init (std::basic_string<C> const& s,
              xml::dom::element<C> const& parent)
        {
          // Note that according to the spec the separator is exactly
          // one space (0x20). This makes our life much easier.
          //

          for (std::size_t i (0), j (s.find (C (' ')));;)
          {
            if (j != std::basic_string<C>::npos)
            {
              push_back (
                traits<X>::create (
                  std::basic_string<C> (s, i, j - i),
                  parent,
                  flags_,
                  container_));

              i = j + 1;
              j = s.find (C (' '), i);
            }
            else
            {
              // Last element.
              push_back (
                traits<X>::create (
                  std::basic_string<C> (s, i),
                  parent,
                  flags_,
                  container_));

              break;
            }
          }
        }

      private:
        flags flags_;
        type* container_;
        base_sequence v_;
      };


      // Specialization for built-in types.
      //
      template <typename X>
      class sequence<X, true>: public std::vector<X>
      {
        typedef std::vector<X> base_sequence;

        /*
      public:
        typedef typename base_sequence::value_type      value_type;
        typedef typename base_sequence::pointer         pointer;
        typedef typename base_sequence::const_pointer   const_pointer;
        typedef typename base_sequence::reference       reference;
        typedef typename base_sequence::const_reference const_reference;

        typedef typename base_sequence::iterator iterator;
        typedef typename base_sequence::const_iterator const_iterator;

        typedef typename base_sequence::reverse_iterator reverse_iterator;
        typedef typename base_sequence::const_reverse_iterator const_reverse_iterator;

        typedef typename base_sequence::size_type       size_type;
        typedef typename base_sequence::difference_type difference_type;
        typedef typename base_sequence::allocator_type  allocator_type;
        */

      public:
        explicit
        sequence (flags = 0, type* = 0)
        {
        }

        sequence (sequence const& s, flags = 0, type* = 0)
            : base_sequence (s)
        {
        }

      public:
        template <typename C>
        explicit
        sequence (xml::dom::element<C> const& e, flags, type*)
        {
          init (e.value (), e);
        }

        template <typename C>
        explicit
        sequence (xml::dom::attribute<C> const& a, flags, type*)
        {
          init (a.value (), a.element ());
        }

        template <typename C>
        sequence (std::basic_string<C> const& s,
                  xml::dom::element<C> const& parent,
                  flags,
                  type*)
        {
          init (s, parent);
        }

      private:
        template <typename C>
        void
        init (std::basic_string<C> const& s,
              xml::dom::element<C> const& parent)
        {
          // Note that according to the spec the separator is exactly
          // one space (0x20). This makes our life much easier.
          //

          for (std::size_t i (0), j (s.find (C (' ')));;)
          {
            if (j != std::basic_string<C>::npos)
            {
              push_back (
                traits<X>::create (
                  std::basic_string<C> (s, i, j - i), parent, 0, 0));

              i = j + 1;
              j = s.find (C (' '), i);
            }
            else
            {
              // Last element.
              push_back (
                traits<X>::create (
                  std::basic_string<C> (s, i), parent, 0, 0));

              break;
            }
          }
        }
      };


      template <typename C, typename X>
      std::basic_ostream<C>&
      operator<< (std::basic_ostream<C>& os, sequence<X> const& v)
      {
        for (typename sequence<X>::const_iterator
               b (v.begin ()), e (v.end ()), i (b); i != e; ++i)
        {
          if (i != b)
            os << C (' ');

          os << *i;
        }

        return os;
      }


      // Proxy pointer that help to fake inheritance from fundamental types.
      //
      template <typename X>
      class proxy_ptr
      {
      public:
        proxy_ptr (X& x)
            : x_ (x)
        {
        }

        operator X* ()
        {
          return x_.real_ptr ();
        }

        operator typename X::base_type* ()
        {
          return &x_.b_;
        }

      private:
        X& x_;
      };

      namespace bits
      {
        template<typename X, typename Y>
        struct return_type
        {
          typedef Y r;
        };

        template<typename X>
        struct return_type<X, X>
        {
          typedef X& r;
        };
      }

      // Fundamental base template.
      //
      template <typename X>
      class fundamental_base: public simple_type
      {
        template <typename>
        friend class proxy_ptr;

        typedef X base_type;

      public:
        fundamental_base ()
            : x_ ()
        {
        }

        fundamental_base (X x)
            : x_ (x)
        {
        }

        fundamental_base (fundamental_base const& other,
                          flags f = 0,
                          type* container = 0)
            : simple_type (other, f, container),
              x_ (other.x_)
        {
        }

        fundamental_base&
        operator= (X const& x)
        {
          if (&x_ != &x)
            x_ = x;

          return *this;
        }

      public:
        template <typename C>
        fundamental_base (xml::dom::element<C> const& e,
                          flags f,
                          type* container);

        template <typename C>
        fundamental_base (xml::dom::attribute<C> const& a,
                          flags f,
                          type* container);

        template <typename C>
        fundamental_base (std::basic_string<C> const& s,
                          xml::dom::element<C> const& e,
                          flags f,
                          type* container);

      public:
        operator X const& () const
        {
          return x_;
        }

        operator X& ()
        {
          return x_;
        }

        template <typename Y>
        operator Y () const
        {
          return Y (x_);
        }

        /*
          This is a nice idea but it doesn't work well
          with function templates, e.g.:

          template<X>
          void destroy (X*);

        proxy_ptr<fundamental_base const>
        operator& () const
        {
          return proxy_ptr<fundamental_base const> (*this);
        }

        proxy_ptr<fundamental_base>
        operator& ()
        {
          return proxy_ptr<fundamental_base> (*this);
        }


      private:
        fundamental_base const*
        real_ptr () const
        {
          return this;
        }

        fundamental_base*
        real_ptr ()
        {
          return this;
        }
        */

      private:
        X x_;
      };

      template <typename C, typename X>
      inline
      std::basic_ostream<C>&
      operator<< (std::basic_ostream<C>& os, fundamental_base<X> x)
      {
        X const& r (x);
        return os << r;
      }

      template <typename C, typename X>
      inline
      std::basic_istream<C>&
      operator>> (std::basic_istream<C>& is, fundamental_base<X>& x)
      {
        X& r (x);
        return is >> r;
      }


      namespace bits
      {
        template <typename C, typename X>
        inline void
        read_fundamental (std::basic_string<C> const& v, X& x)
        {
          std::basic_istringstream<C> is (v);
          is >> x;
        }

        // Specialization for 'signed char'
        //
        template <typename C>
        inline void
        read_fundamental (std::basic_string<C> const& v, signed char& x)
        {
          std::basic_istringstream<C> is (v);

          short t;
          is >> t;

          x = static_cast<signed char> (t);
        }

        // Specialization for 'unsigned char'
        //
        template <typename C>
        inline void
        read_fundamental (std::basic_string<C> const& v, unsigned char& x)
        {
          std::basic_istringstream<C> is (v);

          unsigned short t;
          is >> t;

          x = static_cast<unsigned char> (t);
        }
      }

      template <typename X>
      template <typename C>
      inline fundamental_base<X>::
      fundamental_base (xml::dom::element<C> const& e,
                        flags f,
                        type* container)
          : simple_type (e, f, container)
      {
        bits::read_fundamental (e.value (), x_);
      }

      template <typename X>
      template <typename C>
      inline fundamental_base<X>::
      fundamental_base (xml::dom::attribute<C> const& a,
                        flags f,
                        type* container)
          : simple_type (a, f, container)
      {
        bits::read_fundamental (a.value (), x_);
      }

      template <typename X>
      template <typename C>
      inline fundamental_base<X>::
      fundamental_base (std::basic_string<C> const& s,
                        xml::dom::element<C> const& e,
                        flags f,
                        type* container)
          : simple_type (s, e, f, container)
      {
        bits::read_fundamental (s, x_);
      }
    }
  }
}

#endif  // XSD_CXX_TREE_ELEMENTS_HXX

#include <xsd/cxx/tree/elements.ixx>
