// file      : xsd/cxx/tree/types.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_TYPES_HXX
#define XSD_CXX_TREE_TYPES_HXX

#include <cstdlib> // std::size_t
#include <string>
#include <ostream>

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

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

namespace xsd
{
  namespace cxx
  {
    namespace tree
    {
      // string
      //
      template <typename C>
      class string_template: public std::basic_string<C>,
                             public type

      {
      protected:
        typedef std::basic_string<C> primary_type;
        typedef std::basic_string<C> base_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        string_template ()
        {
        }

        string_template (C const* s)
            : base_type (s)
        {
        }

        string_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        string_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        string_template (primary_type const& str)
            : base_type (str)
        {
        }

        string_template (primary_type const& str,
                         std::size_t pos,
                         std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        explicit
        string_template (xml::dom::element<C> const& e)
            : base_type (e.value ())
        {
        }

        explicit
        string_template (xml::dom::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

        string_template (std::basic_string<C> const& s,
                         xml::dom::element<C> const&)
            : base_type (s)
        {
        }

      public:
        string_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        string_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        string_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };


      // normalized_string: string
      //
      template <typename C>
      class normalized_string_template: public string_template<C>
      {
      protected:
        typedef string_template<C> base_type;
        typedef typename base_type::primary_type primary_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        normalized_string_template ()
        {
        }

        normalized_string_template (C const* s)
            : base_type (s)
        {
        }

        normalized_string_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        normalized_string_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        normalized_string_template (primary_type const& str)
            : base_type (str)
        {
        }

        normalized_string_template (primary_type const& str,
                                    std::size_t pos,
                                    std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        explicit
        normalized_string_template (xml::dom::element<C> const& e)
            : base_type (e.value ())
        {
        }

        explicit
        normalized_string_template (xml::dom::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

        normalized_string_template (std::basic_string<C> const& s,
                         xml::dom::element<C> const&)
            : base_type (s)
        {
        }

      public:
        normalized_string_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        normalized_string_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        normalized_string_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };


      // token: normalized_string
      //
      template <typename C>
      class token_template: public normalized_string_template<C>
      {
      protected:
        typedef normalized_string_template<C> base_type;
        typedef typename base_type::primary_type primary_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        token_template ()
        {
        }

        token_template (C const* s)
            : base_type (s)
        {
        }

        token_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        token_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        token_template (primary_type const& str)
            : base_type (str)
        {
        }

        token_template (primary_type const& str,
                        std::size_t pos,
                        std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        explicit
        token_template (xml::dom::element<C> const& e)
            : base_type (e.value ())
        {
        }

        explicit
        token_template (xml::dom::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

        token_template (std::basic_string<C> const& s,
                        xml::dom::element<C> const&)
            : base_type (s)
        {
        }

      public:
        token_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        token_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        token_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };


      // nmtoken: token
      //
      template <typename C>
      class nmtoken_template: public token_template<C>
      {
      protected:
        typedef token_template<C> base_type;
        typedef typename base_type::primary_type primary_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        nmtoken_template ()
        {
        }

        nmtoken_template (C const* s)
            : base_type (s)
        {
        }

        nmtoken_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        nmtoken_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        nmtoken_template (primary_type const& str)
            : base_type (str)
        {
        }

        nmtoken_template (primary_type const& str,
                          std::size_t pos,
                          std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        explicit
        nmtoken_template (xml::dom::element<C> const& e)
            : base_type (e.value ())
        {
        }

        explicit
        nmtoken_template (xml::dom::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

        nmtoken_template (std::basic_string<C> const& s,
                          xml::dom::element<C> const&)
            : base_type (s)
        {
        }

      public:
        nmtoken_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        nmtoken_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        nmtoken_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };


      // nmtokens: sequence<nmtoken>
      //
      template <typename C>
      class nmtokens_template: public sequence<nmtoken_template<C> >
      {
      public:
        explicit
        nmtokens_template (xml::dom::element<C> const& e)
            : sequence<nmtoken_template<C> > (e)
        {
        }

        explicit
        nmtokens_template (xml::dom::attribute<C> const& a)
            : sequence<nmtoken_template<C> > (a)
        {
        }

        nmtokens_template (std::basic_string<C> const& s,
                           xml::dom::element<C> const& parent)
            : sequence<nmtoken_template<C> > (s, parent)
        {
        }
      };

      /*
      template <typename C>
      inline
      std::basic_ostream<C>&
      operator<< (std::basic_ostream<C>& os, nmtokens_template<C> const& t)
      {
        for (typename nmtokens_template<C>::const_iterator
               b (t.begin ()), e (t.end ()), i (b); i != e; ++i)
        {
          if (i != b)
            os << C (' ');

          os << *i;
        }

        return os;
      }
      */


      // name: token
      //
      template <typename C>
      class name_template: public token_template<C>
      {
      protected:
        typedef token_template<C> base_type;
        typedef typename base_type::primary_type primary_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        name_template ()
        {
        }

        name_template (C const* s)
            : base_type (s)
        {
        }

        name_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        name_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        name_template (primary_type const& str)
            : base_type (str)
        {
        }

        name_template (primary_type const& str,
                       std::size_t pos,
                       std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        explicit
        name_template (xml::dom::element<C> const& e)
            : base_type (e.value ())
        {
        }

        explicit
        name_template (xml::dom::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

        name_template (std::basic_string<C> const& s,
                       xml::dom::element<C> const&)
            : base_type (s)
        {
        }

      public:
        name_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        name_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        name_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };


      // ncname: name
      //
      template <typename C>
      class ncname_template: public name_template<C>
      {
      protected:
        typedef name_template<C> base_type;
        typedef typename base_type::primary_type primary_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        ncname_template ()
        {
        }

        ncname_template (C const* s)
            : base_type (s)
        {
        }

        ncname_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        ncname_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        ncname_template (primary_type const& str)
            : base_type (str)
        {
        }

        ncname_template (primary_type const& str,
                         std::size_t pos,
                         std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        explicit
        ncname_template (xml::dom::element<C> const& e)
            : base_type (e.value ())
        {
        }

        explicit
        ncname_template (xml::dom::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

        ncname_template (std::basic_string<C> const& s,
                         xml::dom::element<C> const&)
            : base_type (s)
        {
        }

      public:
        ncname_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        ncname_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        ncname_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };


      // language: token
      //
      template <typename C>
      class language_template: public token_template<C>
      {
      protected:
        typedef token_template<C> base_type;
        typedef typename base_type::primary_type primary_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        language_template ()
        {
        }

        language_template (C const* s)
            : base_type (s)
        {
        }

        language_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        language_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        language_template (primary_type const& str)
            : base_type (str)
        {
        }

        language_template (primary_type const& str,
                           std::size_t pos,
                           std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        explicit
        language_template (xml::dom::element<C> const& e)
            : base_type (e.value ())
        {
        }

        explicit
        language_template (xml::dom::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

        language_template (std::basic_string<C> const& s,
                           xml::dom::element<C> const&)
            : base_type (s)
        {
        }

      public:
        language_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        language_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        language_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };


      //
      //
      template <typename C>
      struct identity_impl: identity
      {
        identity_impl (ncname_template<C> const& id)
            : id_ (id)
        {
        }

        virtual bool
        before (identity const& y) const
        {
          return id_ < dynamic_cast<identity_impl const&> (y).id_;
        }

        virtual void
        throw_duplicate_id () const
        {
          throw duplicate_id<C> (id_);
        }

      private:
        ncname_template<C> const& id_;
      };


      // id: ncname
      //
      template <typename C>
      class id_template: public ncname_template<C>
      {
      protected:
        typedef ncname_template<C> base_type;
        typedef typename base_type::primary_type primary_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;
        using base_type::empty;

      public:
        ~id_template()
        {
          unregister_id ();
        }

      public:
        id_template ()
            : identity_ (*this)
        {
        }

        id_template (C const* s)
            : base_type (s), identity_ (*this)
        {
        }

        id_template (C const* s, std::size_t n)
            : base_type (s, n), identity_ (*this)
        {
        }

        id_template (std::size_t n, C c)
            : base_type (n, c), identity_ (*this)
        {
        }

        id_template (primary_type const& str)
            : base_type (str), identity_ (*this)
        {
        }

        id_template (primary_type const& str,
                     std::size_t pos,
                     std::size_t n = npos)
            : base_type (str, pos, n), identity_ (*this)
        {
        }

      public:
        id_template (id_template const& str)
            : base_type (str), identity_ (*this)
        {
        }

      public:
        explicit
        id_template (xml::dom::element<C> const& e)
            : base_type (e.value ()), identity_ (*this)
        {
        }

        explicit
        id_template (xml::dom::attribute<C> const& a)
            : base_type (a.value ()), identity_ (*this)
        {
        }

        id_template (std::basic_string<C> const& s,
                     xml::dom::element<C> const&)
            : base_type (s), identity_ (*this)
        {
        }

      public:
        id_template&
        operator= (C c)
        {
          unregister_id ();
          base () = c;
          register_id ();

          return *this;
        }

        id_template&
        operator= (C const* s)
        {
          unregister_id ();
          base () = s;
          register_id ();

          return *this;
        }

        id_template&
        operator= (primary_type const& str)
        {
          unregister_id ();
          base () = str;
          register_id ();

          return *this;
        }

        id_template&
        operator= (id_template const& str)
        {
          unregister_id ();
          base () = str;
          register_id ();

          return *this;
        }

      public:
        using base_type::container;
        using base_type::root;

        virtual void
        container (type* i)
        {
          unregister_id ();

          type::container (i);

          register_id ();
        }

      private:
        void
        register_id ()
        {
          if (container () != this && !empty ())
          {
            //std::wcerr << "registering " << container ()
            //           << " as '" << *this
            //           << "' on " << container () << std::endl;
            container ()->register_id (identity_, container ());
          }
        }

        void
        unregister_id ()
        {
          if (container () != this && !empty ())
          {
            //std::wcerr << "un-registering " << container ()
            //           << " as '" << *this
            //           << "' on " << container () << std::endl;
            container ()->unregister_id (identity_);
          }
        }

      private:
        identity_impl<C> identity_;
      };


      // idref: ncname
      //
      template <typename X, typename C>
      class idref_template: public ncname_template<C>
      {
      protected:
        typedef ncname_template<C> base_type;
        typedef typename base_type::primary_type primary_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        typedef X type;

      public:
        using base_type::npos;
        using base_type::empty;

        using base_type::root;
        using base_type::container;

      public:
        idref_template ()
            : identity_ (*this)
        {
        }

        idref_template (C const* s)
            : base_type (s), identity_ (*this)
        {
        }

        idref_template (C const* s, std::size_t n)
            : base_type (s, n), identity_ (*this)
        {
        }

        idref_template (std::size_t n, C c)
            : base_type (n, c), identity_ (*this)
        {
        }

        idref_template (primary_type const& str)
            : base_type (str), identity_ (*this)
        {
        }

        idref_template (primary_type const& str,
                        std::size_t pos,
                        std::size_t n = npos)
            : base_type (str, pos, n), identity_ (*this)
        {
        }

      public:
        idref_template (idref_template const& str)
            : base_type (str),
              identity_ (*this)
        {
        }

      public:
        explicit
        idref_template (xml::dom::element<C> const& e)
            : base_type (e.value ()), identity_ (*this)
        {
        }

        explicit
        idref_template (xml::dom::attribute<C> const& a)
            : base_type (a.value ()), identity_ (*this)
        {
        }

        idref_template (std::basic_string<C> const& s,
                        xml::dom::element<C> const&)
            : base_type (s), identity_ (*this)
        {
        }

      public:
        idref_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        idref_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        idref_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        idref_template&
        operator= (idref_template const& str)
        {
          base () = str;
          return *this;
        }

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

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

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

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

        X const*
        get () const
        {
          return dynamic_cast<X const*> (get_ ());
        }

        X*
        get ()
        {
          return dynamic_cast<X*> (get_ ());
        }

        // conversion to bool
        //
        typedef void (idref_template::*bool_convertible)();

        operator bool_convertible () const
        {
          return get_ () ? &idref_template::true_ : 0;
        }

      private:
        tree::type const*
        get_ () const
        {
          if (!empty () && container () != this)
          {
            return root ()->lookup_id (identity_);
          }
          else
            return 0;
        }

        tree::type*
        get_ ()
        {
          if (!empty () && container () != this)
          {
            return root ()->lookup_id (identity_);
          }
          else
            return 0;
        }

      private:
        void
        true_ ()
        {
        }

      private:
        identity_impl<C> identity_;
      };


      // idrefs: sequence<idref>
      //
      template <typename X, typename C>
      class idrefs_template: public sequence<idref_template<X, C> >
      {
      public:
        explicit
        idrefs_template (xml::dom::element<C> const& e)
            : sequence<idref_template<X, C> > (e)
        {
        }

        explicit
        idrefs_template (xml::dom::attribute<C> const& a)
            : sequence<idref_template<X, C> > (a)
        {
        }

        idrefs_template (std::basic_string<C> const& s,
                         xml::dom::element<C> const& parent)
            : sequence<idref_template<X, C> > (s, parent)
        {
        }
      };

      /*
      template <typename C>
      inline
      std::basic_ostream<C>&
      operator<< (std::basic_ostream<C>& os, idrefs_template<C> const& r)
      {
        for (typename idrefs_template<C>::const_iterator
               b (r.begin ()), e (r.end ()), i (b); i != e; ++i)
        {
          if (i != b)
            os << C (' ');

          os << *i;
        }

        return os;
      }
      */

      // uri
      //
      template <typename C>
      class uri_template: public std::basic_string<C>,
                          public type
      {
      protected:
        typedef std::basic_string<C> primary_type;
        typedef std::basic_string<C> base_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        uri_template ()
        {
        }

        uri_template (C const* s)
            : base_type (s)
        {
        }

        uri_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        uri_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        uri_template (primary_type const& str)
            : base_type (str)
        {
        }

        uri_template (primary_type const& str,
                      std::size_t pos,
                      std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        explicit
        uri_template (xml::dom::element<C> const& e)
            : base_type (e.value ())
        {
        }

        explicit
        uri_template (xml::dom::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

        uri_template (std::basic_string<C> const& s,
                      xml::dom::element<C> const&)
            : base_type (s)
        {
        }

      public:
        uri_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        uri_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        uri_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };


      // qname
      //
      template <typename C>
      class qname_template: public type
      {
      public:
        qname_template (uri_template<C> const& ns,
                        ncname_template<C> const& name)
            : ns_ (ns),
              name_ (name)
        {
        }
      public:
        explicit
        qname_template (xml::dom::element<C> const& e)
            : ns_ (xml::dom::ns_name (e, e.value ())),
              name_ (xml::uq_name (e.value ()))
        {
        }

        explicit
        qname_template (xml::dom::attribute<C> const& a)
            : ns_ (xml::dom::ns_name (a.element (), a.value ())),
              name_ (xml::uq_name (a.value ()))
        {
        }

        qname_template (std::basic_string<C> const& s,
                        xml::dom::element<C> const& parent)
            : ns_ (xml::dom::ns_name (parent, s)),
              name_ (xml::uq_name (s))
        {
        }

      public:
        uri_template<C> const&
        namespace_ () const
        {
          return ns_;
        }

        ncname_template<C> const&
        name () const
        {
          return name_;
        }

      private:
        uri_template<C> ns_;
        ncname_template<C> name_;
      };

      template <typename C>
      inline
      std::basic_ostream<C>&
      operator<< (std::basic_ostream<C>& os, qname_template<C> const& n)
      {
        return os << n.namespace_ () << C ('#') << n.name ();
      }


      // base64_binary
      //
      template <typename C>
      class base64_binary_template: public std::basic_string<C>,
                                    public type
      {
      protected:
        typedef std::basic_string<C> primary_type;
        typedef std::basic_string<C> base_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        base64_binary_template ()
        {
        }

        base64_binary_template (C const* s)
            : base_type (s)
        {
        }

        base64_binary_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        base64_binary_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        base64_binary_template (primary_type const& str)
            : base_type (str)
        {
        }

        base64_binary_template (primary_type const& str,
                                std::size_t pos,
                                std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        explicit
        base64_binary_template (xml::dom::element<C> const& e)
            : base_type (e.value ())
        {
        }

        explicit
        base64_binary_template (xml::dom::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

        base64_binary_template (std::basic_string<C> const& s,
                                xml::dom::element<C> const&)
            : base_type (s)
        {
        }

      public:
        base64_binary_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        base64_binary_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        base64_binary_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };


      // hex_binary
      //
      template <typename C>
      class hex_binary_template: public std::basic_string<C>,
                                 public type
      {
      protected:
        typedef std::basic_string<C> primary_type;
        typedef std::basic_string<C> base_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        hex_binary_template ()
        {
        }

        hex_binary_template (C const* s)
            : base_type (s)
        {
        }

        hex_binary_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        hex_binary_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        hex_binary_template (primary_type const& str)
            : base_type (str)
        {
        }

        hex_binary_template (primary_type const& str,
                             std::size_t pos,
                             std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        explicit
        hex_binary_template (xml::dom::element<C> const& e)
            : base_type (e.value ())
        {
        }

        explicit
        hex_binary_template (xml::dom::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

        hex_binary_template (std::basic_string<C> const& s,
                             xml::dom::element<C> const&)
            : base_type (s)
        {
        }

      public:
        hex_binary_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        hex_binary_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        hex_binary_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };


      // date
      //
      template <typename C>
      class date_template: public std::basic_string<C>,
                           public type
      {
      protected:
        typedef std::basic_string<C> primary_type;
        typedef std::basic_string<C> base_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        date_template ()
        {
        }

        date_template (C const* s)
            : base_type (s)
        {
        }

        date_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        date_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        date_template (primary_type const& str)
            : base_type (str)
        {
        }

        date_template (primary_type const& str,
                       std::size_t pos,
                       std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        explicit
        date_template (xml::dom::element<C> const& e)
            : base_type (e.value ())
        {
        }

        explicit
        date_template (xml::dom::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

        date_template (std::basic_string<C> const& s,
                       xml::dom::element<C> const&)
            : base_type (s)
        {
        }

      public:
        date_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        date_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        date_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };



      // date_time
      //
      template <typename C>
      class date_time_template: public std::basic_string<C>,
                                public type
      {
      protected:
        typedef std::basic_string<C> primary_type;
        typedef std::basic_string<C> base_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        date_time_template ()
        {
        }

        date_time_template (C const* s)
            : base_type (s)
        {
        }

        date_time_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        date_time_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        date_time_template (primary_type const& str)
            : base_type (str)
        {
        }

        date_time_template (primary_type const& str,
                            std::size_t pos,
                            std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        explicit
        date_time_template (xml::dom::element<C> const& e)
            : base_type (e.value ())
        {
        }

        explicit
        date_time_template (xml::dom::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

        date_time_template (std::basic_string<C> const& s,
                            xml::dom::element<C> const&)
            : base_type (s)
        {
        }

      public:
        date_time_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        date_time_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        date_time_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };


      // duration
      //
      template <typename C>
      class duration_template: public std::basic_string<C>,
                               public type
      {
      protected:
        typedef std::basic_string<C> primary_type;
        typedef std::basic_string<C> base_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        duration_template ()
        {
        }

        duration_template (C const* s)
            : base_type (s)
        {
        }

        duration_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        duration_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        duration_template (primary_type const& str)
            : base_type (str)
        {
        }

        duration_template (primary_type const& str,
                           std::size_t pos,
                           std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        explicit
        duration_template (xml::dom::element<C> const& e)
            : base_type (e.value ())
        {
        }

        explicit
        duration_template (xml::dom::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

        duration_template (std::basic_string<C> const& s,
                           xml::dom::element<C> const&)
            : base_type (s)
        {
        }

      public:
        duration_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        duration_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        duration_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };


      // day
      //
      template <typename C>
      class day_template: public std::basic_string<C>,
                          public type
      {
      protected:
        typedef std::basic_string<C> primary_type;
        typedef std::basic_string<C> base_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        day_template ()
        {
        }

        day_template (C const* s)
            : base_type (s)
        {
        }

        day_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        day_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        day_template (primary_type const& str)
            : base_type (str)
        {
        }

        day_template (primary_type const& str,
                      std::size_t pos,
                      std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        explicit
        day_template (xml::dom::element<C> const& e)
            : base_type (e.value ())
        {
        }

        explicit
        day_template (xml::dom::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

        day_template (std::basic_string<C> const& s,
                      xml::dom::element<C> const&)
            : base_type (s)
        {
        }

      public:
        day_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        day_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        day_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };


      // month
      //
      template <typename C>
      class month_template: public std::basic_string<C>,
                            public type
      {
      protected:
        typedef std::basic_string<C> primary_type;
        typedef std::basic_string<C> base_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        month_template ()
        {
        }

        month_template (C const* s)
            : base_type (s)
        {
        }

        month_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        month_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        month_template (primary_type const& str)
            : base_type (str)
        {
        }

        month_template (primary_type const& str,
                        std::size_t pos,
                        std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        explicit
        month_template (xml::dom::element<C> const& e)
            : base_type (e.value ())
        {
        }

        explicit
        month_template (xml::dom::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

        month_template (std::basic_string<C> const& s,
                        xml::dom::element<C> const&)
            : base_type (s)
        {
        }

      public:
        month_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        month_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        month_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };


      // month_day
      //
      template <typename C>
      class month_day_template: public std::basic_string<C>,
                                public type
      {
      protected:
        typedef std::basic_string<C> primary_type;
        typedef std::basic_string<C> base_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        month_day_template ()
        {
        }

        month_day_template (C const* s)
            : base_type (s)
        {
        }

        month_day_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        month_day_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        month_day_template (primary_type const& str)
            : base_type (str)
        {
        }

        month_day_template (primary_type const& str,
                            std::size_t pos,
                            std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        explicit
        month_day_template (xml::dom::element<C> const& e)
            : base_type (e.value ())
        {
        }

        explicit
        month_day_template (xml::dom::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

        month_day_template (std::basic_string<C> const& s,
                            xml::dom::element<C> const&)
            : base_type (s)
        {
        }

      public:
        month_day_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        month_day_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        month_day_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };


      // year
      //
      template <typename C>
      class year_template: public std::basic_string<C>,
                           public type
      {
      protected:
        typedef std::basic_string<C> primary_type;
        typedef std::basic_string<C> base_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        year_template ()
        {
        }

        year_template (C const* s)
            : base_type (s)
        {
        }

        year_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        year_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        year_template (primary_type const& str)
            : base_type (str)
        {
        }

        year_template (primary_type const& str,
                       std::size_t pos,
                       std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        explicit
        year_template (xml::dom::element<C> const& e)
            : base_type (e.value ())
        {
        }

        explicit
        year_template (xml::dom::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

        year_template (std::basic_string<C> const& s,
                       xml::dom::element<C> const&)
            : base_type (s)
        {
        }

      public:
        year_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        year_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        year_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };


      // year_month
      //
      template <typename C>
      class year_month_template: public std::basic_string<C>,
                                 public type
      {
      protected:
        typedef std::basic_string<C> primary_type;
        typedef std::basic_string<C> base_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        year_month_template ()
        {
        }

        year_month_template (C const* s)
            : base_type (s)
        {
        }

        year_month_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        year_month_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        year_month_template (primary_type const& str)
            : base_type (str)
        {
        }

        year_month_template (primary_type const& str,
                             std::size_t pos,
                             std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        explicit
        year_month_template (xml::dom::element<C> const& e)
            : base_type (e.value ())
        {
        }

        explicit
        year_month_template (xml::dom::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

        year_month_template (std::basic_string<C> const& s,
                             xml::dom::element<C> const&)
            : base_type (s)
        {
        }

      public:
        year_month_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        year_month_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        year_month_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };


      // time
      //
      template <typename C>
      class time_template: public std::basic_string<C>,
                           public type
      {
      protected:
        typedef std::basic_string<C> primary_type;
        typedef std::basic_string<C> base_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        time_template ()
        {
        }

        time_template (C const* s)
            : base_type (s)
        {
        }

        time_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        time_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        time_template (primary_type const& str)
            : base_type (str)
        {
        }

        time_template (primary_type const& str,
                       std::size_t pos,
                       std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        explicit
        time_template (xml::dom::element<C> const& e)
            : base_type (e.value ())
        {
        }

        explicit
        time_template (xml::dom::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

        time_template (std::basic_string<C> const& s,
                       xml::dom::element<C> const&)
            : base_type (s)
        {
        }

      public:
        time_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        time_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        time_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };


      // entity: ncname
      //
      template <typename C>
      class entity_template: public ncname_template<C>
      {
      protected:
        typedef ncname_template<C> base_type;
        typedef typename base_type::primary_type primary_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        entity_template ()
        {
        }

        entity_template (C const* s)
            : base_type (s)
        {
        }

        entity_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        entity_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        entity_template (primary_type const& str)
            : base_type (str)
        {
        }

        entity_template (primary_type const& str,
                         std::size_t pos,
                         std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        explicit
        entity_template (xml::dom::element<C> const& e)
            : base_type (e.value ())
        {
        }

        explicit
        entity_template (xml::dom::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

        entity_template (std::basic_string<C> const& s,
                         xml::dom::element<C> const&)
            : base_type (s)
        {
        }

      public:
        entity_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        entity_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        entity_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };


      // entities: sequence<entity>
      //
      template <typename C>
      class entities_template: public sequence<entity_template<C> >
      {
      public:
        explicit
        entities_template (xml::dom::element<C> const& e)
            : sequence<entity_template<C> > (e)
        {
        }

        explicit
        entities_template (xml::dom::attribute<C> const& a)
            : sequence<entity_template<C> > (a)
        {
        }

        entities_template (std::basic_string<C> const& s,
                           xml::dom::element<C> const& parent)
            : sequence<entity_template<C> > (s, parent)
        {
        }
      };

      /*
      template <typename C>
      inline
      std::basic_ostream<C>&
      operator<< (std::basic_ostream<C>& os, entities_template<C> const& en)
      {
        for (typename entities_template<C>::const_iterator
               b (en.begin ()), e (en.end ()), i (b); i != e; ++i)
        {
          if (i != b)
            os << C (' ');

          os << *i;
        }

        return os;
      }
      */
    }
  }
}

#include <xsd/cxx/tree/types.txx>

#endif  // XSD_CXX_TREE_TYPES_HXX
