// file      : xsd/cxx/tree/exceptions.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_EXCEPTIONS_HXX
#define XSD_CXX_TREE_EXCEPTIONS_HXX

#include <string>
#include <vector>
#include <ostream>

#include <xsd/cxx/exceptions.hxx> // xsd::cxx::exception

namespace xsd
{
  namespace cxx
  {
    namespace tree
    {
      //
      //
      template <typename C>
      struct exception: virtual xsd::cxx::exception
      {
        friend
        std::basic_ostream<C>&
        operator<< (std::basic_ostream<C>& os, exception const& e)
        {
          e.print (os);
          return os;
        }

      protected:
        virtual void
        print (std::basic_ostream<C>&) const = 0;
      };


      //
      //
      template <typename C>
      struct error
      {
        error (std::basic_string<C> const& id,
               unsigned long line,
               unsigned long column,
               std::basic_string<C> const& message)
            : id_ (id),
              line_ (line),
              column_ (column),
              message_ (message)
        {
        }

        std::basic_string<C> const&
        id () const
        {
          return id_;
        }

        unsigned long
        line () const
        {
          return line_;
        }

        unsigned long
        column () const
        {
          return column_;
        }

        std::basic_string<C> const&
        message () const
        {
          return message_;
        }

      private:
        std::basic_string<C> id_;
        unsigned long line_;
        unsigned long column_;
        std::basic_string<C> message_;
      };

      // See exceptions.ixx for operator<< (error).


      //
      //
      template <typename C>
      struct errors: std::vector<error<C> >
      {
      };

      // See exceptions.ixx for operator<< (errors).

      //
      //
      template <typename C>
      struct parsing: virtual exception<C>
      {
        virtual
        ~parsing () throw ()
        {
        }

        parsing ()
        {
        }

        parsing (tree::errors<C> const& errors)
            : errors_ (errors)
        {
        }

        tree::errors<C> const&
        errors () const
        {
          return errors_;
        }

        virtual char const*
        what () const throw ()
        {
          return "instance document parsing failed";
        }

      protected:
        virtual void
        print (std::basic_ostream<C>&) const;

      private:
        tree::errors<C> errors_;
      };


      //
      //
      template <typename C>
      struct expected_element: virtual exception<C>
      {
        virtual
        ~expected_element () throw ()
        {
        }

        expected_element (std::basic_string<C> const& name,
                          std::basic_string<C> const& namespace_)
            : name_ (name), namespace__ (namespace_)
        {
        }

        // Expected element.
        //
        std::basic_string<C> const&
        name () const
        {
          return name_;
        }

        std::basic_string<C> const&
        namespace_ () const
        {
          return namespace__;
        }

        virtual char const*
        what () const throw ()
        {
          return "expected element not encountered";
        }

      protected:
        virtual void
        print (std::basic_ostream<C>&) const;

      private:
        std::basic_string<C> name_;
        std::basic_string<C> namespace__;
      };


      //
      //
      template <typename C>
      struct unexpected_element: virtual exception<C>
      {
        virtual
        ~unexpected_element () throw ()
        {
        }

        unexpected_element (std::basic_string<C> const& encountered_name,
                            std::basic_string<C> const& encountered_namespace,
                            std::basic_string<C> const& expected_name,
                            std::basic_string<C> const& expected_namespace)
            : encountered_name_ (encountered_name),
              encountered_namespace_ (encountered_namespace),
              expected_name_ (expected_name),
              expected_namespace_ (expected_namespace)
        {
        }

        // Encountered element.
        //
        std::basic_string<C> const&
        encountered_name () const
        {
          return encountered_name_;
        }

        std::basic_string<C> const&
        encountered_namespace () const
        {
          return encountered_namespace_;
        }

        // Expected element. Maybe be empty.
        //
        std::basic_string<C> const&
        expected_name () const
        {
          return expected_name_;
        }

        std::basic_string<C> const&
        expected_namespace () const
        {
          return expected_namespace_;
        }

        virtual char const*
        what () const throw ()
        {
          return "unexpected element encountered";
        }

      protected:
        virtual void
        print (std::basic_ostream<C>&) const;

      private:
        std::basic_string<C> encountered_name_;
        std::basic_string<C> encountered_namespace_;
        std::basic_string<C> expected_name_;
        std::basic_string<C> expected_namespace_;
      };


      //
      //
      template <typename C>
      struct expected_attribute: virtual exception<C>
      {
        virtual
        ~expected_attribute () throw ()
        {
        }

        expected_attribute (std::basic_string<C> const& name,
                            std::basic_string<C> const& namespace_)
            : name_ (name), namespace__ (namespace_)
        {
        }

        // Expected attribute.
        //
        std::basic_string<C> const&
        name () const
        {
          return name_;
        }

        std::basic_string<C> const&
        namespace_ () const
        {
          return namespace__;
        }

        virtual char const*
        what () const throw ()
        {
          return "expected attribute not encountered";
        }

      protected:
        virtual void
        print (std::basic_ostream<C>&) const;

      private:
        std::basic_string<C> name_;
        std::basic_string<C> namespace__;
      };


      //
      //
      template <typename C>
      struct unexpected_enumerator: virtual exception<C>
      {
        virtual
        ~unexpected_enumerator () throw ()
        {
        }

        unexpected_enumerator (std::basic_string<C> const& enumerator)
            : enumerator_ (enumerator)
        {
        }

        std::basic_string<C> const&
        enumerator () const
        {
          return enumerator_;
        }

        virtual char const*
        what () const throw ()
        {
          return "unexpected enumerator encountered";
        }

      protected:
        virtual void
        print (std::basic_ostream<C>&) const;

      private:
        std::basic_string<C> enumerator_;
      };


      //
      //
      template <typename C>
      struct no_type_info: virtual exception<C>
      {
        virtual
        ~no_type_info () throw ()
        {
        }

        no_type_info (std::basic_string<C> const& type_name,
                      std::basic_string<C> const& type_namespace)
            : type_name_ (type_name),
              type_namespace_ (type_namespace)
        {
        }

        std::basic_string<C> const&
        type_name () const
        {
          return type_name_;
        }

        std::basic_string<C> const&
        type_namespace () const
        {
          return type_namespace_;
        }

        virtual char const*
        what () const throw ()
        {
          return "no type information registered for a type";
        }

      protected:
        virtual void
        print (std::basic_ostream<C>&) const;

      private:
        std::basic_string<C> const& type_name_;
        std::basic_string<C> const& type_namespace_;
      };

      //
      //
      template <typename C>
      struct not_derived: virtual exception<C>
      {
        virtual
        ~not_derived () throw ()
        {
        }

        not_derived (std::basic_string<C> const& base_type_name,
                     std::basic_string<C> const& base_type_namespace,
                     std::basic_string<C> const& derived_type_name,
                     std::basic_string<C> const& derived_type_namespace)
            : base_type_name_ (base_type_name),
              base_type_namespace_ (base_type_namespace),
              derived_type_name_ (derived_type_name),
              derived_type_namespace_ (derived_type_namespace)
        {
        }

        std::basic_string<C> const&
        base_type_name () const
        {
          return base_type_name_;
        }

        std::basic_string<C> const&
        base_type_namespace () const
        {
          return base_type_namespace_;
        }

        std::basic_string<C> const&
        derived_type_name () const
        {
          return derived_type_name_;
        }

        std::basic_string<C> const&
        derived_type_namespace () const
        {
          return derived_type_namespace_;
        }

        virtual char const*
        what () const throw ()
        {
          return "type is not derived";
        }

      protected:
        virtual void
        print (std::basic_ostream<C>&) const;

      private:
        std::basic_string<C> const& base_type_name_;
        std::basic_string<C> const& base_type_namespace_;
        std::basic_string<C> const& derived_type_name_;
        std::basic_string<C> const& derived_type_namespace_;
      };


      //
      //
      template <typename C>
      struct duplicate_id: virtual exception<C>
      {
        virtual
        ~duplicate_id () throw ()
        {
        }

        duplicate_id (std::basic_string<C> const& id)
            : id_ (id)
        {
        }

        std::basic_string<C> const&
        id () const
        {
          return id_;
        }

        virtual char const*
        what () const throw ()
        {
          return "ID already exist";
        }

      protected:
        virtual void
        print (std::basic_ostream<C>&) const;

      private:
        std::basic_string<C> id_;
      };


      //
      //
      template <typename C>
      struct serialization: virtual exception<C>
      {
        virtual
        ~serialization () throw ()
        {
        }

        serialization ()
        {
        }

        serialization (tree::errors<C> const& errors)
            : errors_ (errors)
        {
        }

        tree::errors<C> const&
        errors () const
        {
          return errors_;
        }

        virtual char const*
        what () const throw ()
        {
          return "representation serialization failed";
        }

      protected:
        virtual void
        print (std::basic_ostream<C>&) const;

      private:
        tree::errors<C> errors_;
      };


      //
      //
      template <typename C>
      struct no_namespace_mapping: virtual exception<C>
      {
        virtual
        ~no_namespace_mapping () throw ()
        {
        }

        no_namespace_mapping (std::basic_string<C> const& namespace_)
            : namespace__ (namespace_)
        {
        }

        // Namespace for which prefix-namespace mapping hasn't been
        // provided.
        //
        std::basic_string<C> const&
        namespace_ () const
        {
          return namespace__;
        }

        virtual char const*
        what () const throw ()
        {
          return "no mapping provided for a namespace";
        }

      protected:
        virtual void
        print (std::basic_ostream<C>&) const;

      private:
        std::basic_string<C> namespace__;
      };


      //
      //
      template <typename C>
      struct no_prefix_mapping: virtual exception<C>
      {
        virtual
        ~no_prefix_mapping () throw ()
        {
        }

        no_prefix_mapping (std::basic_string<C> const& prefix)
            : prefix_ (prefix)
        {
        }

        // Prefix for which prefix-namespace mapping hasn't been
        // provided.
        //
        std::basic_string<C> const&
        prefix () const
        {
          return prefix_;
        }

        virtual char const*
        what () const throw ()
        {
          return "no mapping provided for a namespace prefix";
        }

      protected:
        virtual void
        print (std::basic_ostream<C>&) const;

      private:
        std::basic_string<C> prefix_;
      };


      //
      //
      template <typename C>
      struct xsi_already_in_use: virtual exception<C>
      {
        virtual char const*
        what () const throw ()
        {
          return "namespace prefix 'xsi' is already in use and no "
            "user-defined mapping has been provided for namespace "
            "'http://www.w3.org/2001/XMLSchema-instance'";
        }

      protected:
        virtual void
        print (std::basic_ostream<C>&) const;
      };
    }
  }
}

#endif  // XSD_CXX_TREE_EXCEPTIONS_HXX

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