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

#ifndef XSD_CXX_PARSER_EXCEPTIONS_HXX
#define XSD_CXX_PARSER_EXCEPTIONS_HXX

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

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

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

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


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

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

        unsigned long
        line () const
        {
          return line_;
        }

        unsigned long
        column () const
        {
          return column_;
        }

        const std::basic_string<C>&
        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 (const parser::errors<C>& errors)
            : errors_ (errors)
        {
        }

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

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

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

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

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

        expected_element (const std::basic_string<C>& expected_namespace,
                          const std::basic_string<C>& expected_name)
            : expected_namespace_ (expected_namespace),
              expected_name_ (expected_name)
        {
        }

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

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

        const std::basic_string<C>&
        expected_name () const
        {
          return expected_name_;
        }


        // Encountered element namespace and name are empty if none
        // encountered.
        //
        const std::basic_string<C>&
        encountered_namespace () const
        {
          return encountered_namespace_;
        }

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

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

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

      private:
        std::basic_string<C> expected_namespace_;
        std::basic_string<C> expected_name_;

        std::basic_string<C> encountered_namespace_;
        std::basic_string<C> encountered_name_;
      };


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

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

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

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

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

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

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

#endif  // XSD_CXX_PARSER_EXCEPTIONS_HXX

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